Here is a question wich offer a solution to print all properties. But in fact it prints all properties from .properties files in application sources, system and environment properties. But it ignore all properties from
additional-spring-configuration-metadata.json
spring-configuration-metadata.json
spring-autoconfigure-metadata.properties
and others from json or properties in project dependecies
any properties which is considered as present in org.springframework.boot.autoconfigure.condition.ConditionalOnProperty annotation, with matchIfMissing key word, like that #ConditionalOnProperty(prefix = "spring.data.solr.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
Even I can not find any variable inside Environment env which points to any of these properties.
So is there a way to print all properties both from current application sources and from imported dependencies/jars, especially which are generated via by annotatios?
Related
I have a library that has a configuration class with #ConfigurationProperties(prefix ="b") and #ConditionalOnProperty(prefix = "b", name= "c"), in the project where I included this configuration class, the property "b" is nested under a property called "a" instead of being at the root level of the properties.yml, with this the property "b" name is "a.b" and the configuration class will get ignored, the property name needs to be kept "a.b" in the property file, is there a way to tell spring boot to ignore the "a" prefix for the property "b" or to rewrite the property name from "a.b" to "b" after application.yml gets loaded ?
You can (probably, depending on the exact context of the config class you're working with) use YAML anchor and alias to meet this need. YAML anchors are similar to anchors (<a> tags) in HTML; you mark some part of the yaml with an anchor, then refer to it with a reference somewhere else. The reference is an alias to the anchored value.
In your example, assuming the conditional config class is something like this:
#Configuration
#ConditionalOnProperty(prefix = "b", name = "foo")
#ConfigurationProperties(prefix ="b")
#Getter #Setter
public class SO_75435896 {
private String foo;
}
You can have a YAML config like this to populate it:
a.b: &b-alias
foo: bar
b: *b-alias
The anchor name (b-alias in my example) can be whatever you want, there's nothing special about that name I chose.
If you want to read more about YAML anchors, this is a decent explanation. It's part of Bitbucket documentation, but provides a pretty good general-purpose explanation with examples. There are, of course, plenty of other web pages about YAML anchors.
So your configuration class and properties files cannot be adapted. You can rename it at runtime in your application.yml :
BProperties
#ConfigurationProperties(prefix ="b")
public class BProperties {
private String c;
private String d;
}
And this properties file :
my-props-file.properties
a.b.c=value1
a.b.d=value2
You can rename the properties at runtime in your application.yml (define in classpath under src/main/ressources/) :
application.yml
b:
c: ${a.b.c}
d: ${a.b.d}
I have some properties, where some initial part is same and remaining is different for all properties.
can have 1 dot (.) 2,3 or more.
I can't use #ConfigurationProperties to loca these with prefix ="com.some.props" because remaining properties are different
com:
some:
props:
prop1:
someProp: value
prop2:
anotherProp:
innerprop: value2
So I created a custom props class and used #Value but I have to write full property path for wach variable.
Is there a way I can apply a prefix for all #Value in a class
#Component (prefix="com.some.props") //Not a valid code, but want something of this sort.
class props {
#Values ("${prop1.someprop}")
String someprop;
#Values ("${prop2.anotherProp.innerProp}")
String somethingElse;
}
I have an application.yaml file which specifies the service's name:
spring:
application:
name: "my-microservice"
Now, when I try to fetch it using #Value("spring.application.name") inside my code, I'm able to do that successfully.
But I'm also using a "dev" profile for which I created a separate application-dev.yaml, but I didn't specify the spring.application.name inside this yaml.
Now, when I try to run my code, the #Value annotation gives me a null.
I thought that the fields not specified by application-dev.yaml should be populated using application.yaml, but apparently this is not happening.
Am I supposed to just copy every common field from the default to the dev's application file? Or is there any other way? Any help is appreciated, Thanks :)
You need to use Spring Expression Language which says we should write it as
#Value("${spring.application.name}")
private String appName;
For Default value if key is not present in yaml/yml or properties file
#Value("${spring.application.name: defaultValue}")
private String appName;
The last way you can fetch value is using environment object
#Autowired
private Environment environment;
String appName = environment.get("spring.application.name");
Ok I figured out the problem.
It is true that the default application.yaml properties are read by spring for all profiles (unless they have been overwritten by a profile's application file)
But in my case, I was trying to use the #Value annotation on a static field.
#Value("${spring.application.name}")
private static String applicationName;
This caused the null exception in my code. Removing the static context from the field worked for me.
I want to inject some values from a YAML to the Spring context.
The structure of the YAML is similar so I did not want to duplicate code, but the Spring startup is failing because it is not being able to inject the value to the placeholder.
Please note my application.properties:
server.port=8084
activeProfile=dev
autoAgents.supplier.id=0
autoAgents.supplier.name=test
autoAgents.supplier.serviceType=REST
autoAgents.supplier.authType=1
autoAgents.supplier.adapter=test
autoAgents.supplier.username=test
autoAgents.supplier.secret=test
autoAgents.supplier.apiPassword=12345
autoAgents.client.id=1
autoAgents.client.name=test
autoAgents.client.serviceType=REST
autoAgents.client.authType=1
autoAgents.client.adapter=
autoAgents.client.username=test
autoAgents.client.secret=test
autoAgents.client.apiPassword=12345
Then I am injecting this values on the YAML, application.yml
activeProfile: ${activeProfile}
autoAgents:
supplier:
isSupplier: true
meta:
id: ${autoAgents.supplier.id}
name: ${autoAgents.supplier.name}
serviceType: ${autoAgents.supplier.serviceType}
authType: ${autoAgents.supplier.authType}
adapter: ${autoAgents.supplier.adapter}
credentials:
username: ${autoAgents.supplier.username}
secret: ${autoAgents.supplier.secret}
apiPassword: ${autoAgents.supplier.apiPassword}
client:
isSupplier: false
meta:
id: ${autoAgents.client.id}
name: ${autoAgents.client.name}
serviceType: ${autoAgents.client.serviceType}
authType: ${autoAgents.client.authType}
adapter: ${autoAgents.client.adapter}
credentials:
username: ${autoAgents.client.username}
secret: ${autoAgents.client.secret}
apiPassword: ${autoAgents.client.apiPassword}
And then I am importing this to a configuration property context:
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
#Data
public class TwoConnectConfigurationProperties {
private String activeProfile;
#Value("${autoAgents.supplier}")
private AutoAgentDup supplier;
#Value("${autoAgents.client}")
private AutoAgentDup client;
}
But #Value("${autoAgents.supplier}") is not working.
Please advise.
As mentioned earlier it does not make sense to inject values to yaml, you can just create the "application.yaml" with the values directly. And just delete the ".properies" file.
You might want to take a look how to easily inject the properties with common suffix into a bean. Its nicely described here:
https://www.baeldung.com/configuration-properties-in-spring-boot
You will have a bean:
#Configuration
#ConfigurationProperties(prefix = "autoAgents.supplier")
public class AutoAgentSupplierProperties {
private long id;
private String name;
// ... rest of the properies properties
}
You might want the same for the "auto.agent" client.
If you want to avoid code duplication, you can have a bean with the common properties. Extend that class with 2 new classes. One for supplier and one for agent - and annotate those with
#ConfigurationProperties
annotation.
Why you need "nested properties"? If you only want to access them in application, just take values from .properties file and fill them as values to .yml file. E.g.: profile: dev, or
autoAgents:
client:
id: 1
Properties from .yml file can be accessed from code same way as from .properties file.
Your problem is in way how you access properties. When you use "#Configuration properties", you have to specific which one to use (e.g. #ConfigurationProperties("autoAgents.client").
In my application, I have dozen of properties mapped to my bean attributes like that:
#Value("#{props['prop1']}")
private String prop1;
#Value("#{props['prop2']}")
private String prop2;
#Value("#{props['prop3']}")
private String prop3;
In my property file, I always need to define the values:
prop1=value1
prop2=value2
prop3=specific-value
It's heavy because most of the properties are often the same. I would prefer to define default values in my code and then override what I need in my property file. The code can looks like this:
#Value("#{props['prop1'] ?: value1}")
private String prop1;
#Value("#{props['prop2'] ?: value2}")
private String prop2;
#Value("#{props['prop3'] ?: value3}")
private String prop3;
And in my property file, I just change prop3:
prop3=specific-value
This is handy because we have a smaller property file that is easier to maintain. Spring boot can also help more by picking the right property file according to the enabled profile.
Now I have one concern: as a developer, how I can know all the configuration points inside my application? If we are forced to add all the properties to the property file, then we can have the list of supported properties easily. However with an approach where only a few properties are defined, we lose this benefit and it becomes tricky to know what property can be changed.
I'm curious to know how this issue has been already addressed before and how. I would expect to have a utility tool like a maven plugin that can scan my beans, detects inside them the attributes annotated with #Value and prints a table of all properties and their default value defined in the application.