Conventions for naming application.properties - spring

In my Spring application, I am trying to use property-placeholder with profiles test,dev,prod. Also I would like to be able to load the default properties common which are common for all profiles.
<context:property-placeholder
ignore-resource-not-found="false"
location="classpath:application-common.properties,classpath:application-test.properties"/>
This however doesn't work correctly. I am not yet using the variable ${spring.profiles.active}, because it doesn't work correctly even without it. What happens is that whatever is after the hyphen application- is loaded in alphabetical order. Loaded is only the first one, the other one is ignored. So in this case, only -common is loaded. Strange thing is, if I remove the hyphen, it load both files.
Is there some hidden behaviour I am not aware of?

You can use #PropertySource to load 'common' property file.
#PropertySource({
"classpath:application-common.properties"
})
Load environment specific property file by using spring.profiles.active while running your application.
For example , spring.profiles.active=dev

Related

SpringBoot custom spring.config.location

I have a simple SpringBoot application with the following structure:
I'm using a standard application.yml file where I'm storing all the necessary props and use #ConfigurationProperties annotation to inject them where necessary.
Now for one bean I have quite a lot of props and I don't want to overwhelm my common application.yml file with all that props. So I want a separate one (which I placed under service dir in classpath).
According to Spring docs I can use something like:
java -jar myproject.jar --spring.config.location=classpath:/service/application.yml
But that's not working, I got NullPointer which means property was not injected.
What Am I doing wrong? How can I use another *.yml file together with application.yml?
P.S. I know I could place it under the config folder in classpath, but what if I need two custom files?
If you have 2 configs in different places, spring.config.location will accept a comma separated list of those locations
--spring.config.location=classpath:/resources/,classpath:/service/
You could also just call the other file like "config.yml" and then use a different name
--spring.config.name=application,config

context:property-placeholder comma-separated list of resources don't work with system property placeholder

I can't entirely configure property-placeholder from system property because I can't give comma-separated list of resources.
I'm trying to do like:
<context:property-placeholder location="${config-location}" />
I use system property to configure this. It works if I give one location only, like "classpath:main.properties", but it does not if I'm trying this: "classpath:main1.properties,classpath:main2.properties".
If I use this latter exact value directly in xml configuration it works fine. I guess it resolves comma-separation earlier than placeholders. It should be the other way around.
P.S : version 4.3.4
Another possible worth tryout would be,
<context:property-placeholder location="#{systemProperties['config-location']}" />
how to read System environment variable in Spring applicationContext

Spring boot, use profiles to load files

I have used spring-boot profiles to change property values for different environments, now I want to use the same approach to load different resource files, ie example I have dev_queries and prod_queries.xml with sql queries.
How can I make spring-boot load dev_queries.xml if active profile is dev and prod_queries.xml otherwise. I know that I can check the active profile but my idea is to do not add specific logic for handle this situation.
Would it help to externalize the filename as a custom property (docs, especially 24.4)? So that in your properties you would use:
# application-dev.properties
myapp.query-source=dev_queries.xml
# application-production.properties
myapp.query-source=prod_queries.xml
In your application beans this setting can be accessed by using the #Value annotation:
#Value("${myapp.query-source}")
private String querySource; // will be dev_queries.xml or prod_queries.xml
That way in the code where you are loading the xml file you don't have to conditionally check for the currently active profiles but can externalize that setting to the properties.

Spring Boot configuration behaviour with #ConfigurationProperties and Command Line arguments

I seem to be having some funny behaviour with Spring boot on yaml property files im trying to load.
I have a Settings bean that is setup as follows :
#ConfigurationProperties(location = 'config.yml', prefix='settings')
public class Settings {
private String path;
...
}
I've explicitly told spring to look in the config.yml file for property values to bind to the Settings bean. This looks like this:
settings:
path: /yaml_path
This works well, however, I don't seem to be able to override these values from the command line i.e.
java -jar my.jar --settings.path=test
The value that is bound to the settings bean is still /yaml_path but would've expected that the --settings.path=test would override the settings in the yaml.
Interestingly, I've noticed that if i take comment out the path setting from the yaml file, the commandline argument value of test comes through.
Additionally, I've also noticed that if i change my config file from config.yml to application.yml and remove the 'location' attribute from the configuration properties file this gives me the desired desired behaviour, but means that I can't have multiple application.yml files in the classpath as it breaks my multi module application which has configuration files throughout.
Ideal world I would like be able to have modules read configuration from yaml files that contain safe values for that module (i.e. module.yml) and be able to override these values from the commandline if needed. Has anyone figured out how to get commandline arguments passed into the beans this way?
I have created a project on git hub to show case the issue
https://github.com/vcetinick/spring-boot-yaml-test
Running the application displays logging information about what settings are applied. i.e.
java -jar spring-boot-yaml-test-0.0.1-SNAPSHOT.jar --config.path=/test
should override the settings, however, the default /var/tmp is displayed
additionally, when using the application.yml configuration
java -jar spring-boot-yaml-test-0.0.1-SNAPSHOT.jar --app.path=/test
seems to behave as expected where the command line argument overrides the value but only works because its value is defined in the application.yml file.
Looks like the locations attribute is working as designed, however, seems to be at odds with the standard configuration paradigm setup by spring boot (https://github.com/spring-projects/spring-boot/issues/5111). It is meant to override the settings. It looks like this this feature may be removed in a future release of spring boot anyway (https://github.com/spring-projects/spring-boot/issues/5129)

Property-placeholder default value separator

Small question.
We use Spring 3.1 and seem to be having an issue with the value separator (The default value that is).
<context:property-placeholder ignore-resource-not-found="false" ignore-unresolvable="false" location="${app-conf-base-path:classpath:}environment/app-conf-${spring.profiles.active:test}.properties" />
We filter the properties being deployed based on maven environment profiles. If no maven environment profile was provided all environment property files will loaded in the war and put on the classpath.
The actual environment specific settings are loaded at runtime using spring profiles. The part that is giving us an issue though is ${app-conf-base-path:classpath:} because it seems he can not resolve this. I believe this is because the placeholder is split using the last occurrence of the default value separator.
Why we want this is because we want him to look on the app-conf-base-path unless this is not defined as JVM parameter. In that case he should look in the classpath.
I tried:
Placeholder configurer with a value separator == '?' with no avail.
Anyone got an idea of an alternative?
I solved the problem by making sure external configuration files are added to the classpath of the server when loading it's classloaders. This way I don't need a placeholder to point to a file:// type location.
I added a export line to the setclasspath.sh of tomcat to add the external file to the environment variable CLASSPATH.

Resources