SpringBoot custom spring.config.location - spring-boot

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

Related

Spring #Value property doesn't read nested YAML properties correctly

I have a simple YAML property policy.statement that I want to read from a configuration java file using #PropertySource and #Value annotations. If I use only #Value(${statement}) it reads ok, but if I use #Value(${policy.statement}) if can't find. And at the YAML file I use policy: [enter] statement: value . Why doesn't #Value work if I use ${property1.property2} but only if I use ${property2} alone ? It doesn't make sense. Print and source link attached.
full project at the "doubt" branch at the project link:
https://github.com/danielpm1982/springboot2-health-record/tree/doubt
[SOLVED]
You can't use PropertySource or PropertySources Spring Annotation with custom named yaml files... only with .properties txt files. So, to solve the problem, instead of using custom named .yaml files I had to use the default named application.yaml. This way there's no need to use PropertySource for the .yaml file (only for the .properties ones) and it all worked fine, including the different profile selection of my yaml file properties according to the profile set at the application.properties .
Thanks to Deadpool:
https://stackoverflow.com/users/9959152/deadpool
Full project available at the master branch of the project link:
https://github.com/danielpm1982/springboot2-health-record

Spring Boot 2: Using external Property-Files

I have a executeable jar what I want to configure by properties outside of the jar. What works fine is application.properties, when putting it to config folder close to the jar. But I have a second property-file what seems not to be picked up and I would like to have the best practice for that.
The folder config looks like:
In the config-folder you will find:
Both property-files are also in the src/main/resources folder.
My StartClass looks like:
#SpringBootApplication
#PropertySource("migration-shrink.properties")
public class MigrationShrinkApplication implements CommandLineRunner {}
My bat file looks like:
java -jar migration-shrink-0.0.1-SNAPSHOT.jar -Dspring.config.location=./config/migration-shrink.properties
I wanted to separate Spring-Configuration from Application-Configuration, thats why I have two different property-files.
Thank you!
The #PropertySource annotation is not necessary.
As of Spring Boot 2.0, you can declare additional locations with:
-Dspring.config.additional-location=./config/migration-shrink.properties
Keep in mind that those additional locations are searched before others, so values can be overridden in the other locations.
See the Spring Boot reference documentation.

Using Expressions in Spring application.properties file

Can expressions be used as a right-hand-side value in a Spring application.properties file?
For example, something like this:
logging.level.com.acme=#{'${MY_RUN_ENV}'=='PROD'?'WARN':'DEBUG'}
That, specifically, does not work. But, I'm wondering if I can do something similar to what's intended there
No you can not use SpEL within properties files.
Finally, while you can write a SpEL expression in #Value, such
expressions are not processed from Application property files.
You can however use placeholders within properties files, eg:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
For your use case, you should look at the profile-specific configuration mechanism.
Which allows you to load different config based on an environment profile.
No this is not possible, From spring boot reference:
Feature #ConfigurationProperties
SpEL evaluation No
Instead you can have an application-default.properties in production and in it define loglevel=WARN.
And in your application.properties:
loglevel=DEBUG
logging.level.com.acme=${loglevel}
The profile-specific properties file(-default by default) should override the properties from application.properties, more info here.
Use profile based properties file.
In application-dev.properties :
logging.level.com.acme=WARN
and in application-prod.properties :
logging.level.com.acme=DEBUG
FYI when spring boot doesn't find a propertie in a profile based file it use the value in the default one . So you can set properties in application.properties and override them in a profile based file when their value changed.

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)

Spring Boot profile specific properties

I'm using Sprint Boot, and would like to have multiple profile specific property files. The docs state:
In addition to application.properties files, profile specific
properties can also be defined using the naming convention
application-{profile}.properties.
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-profile-specific-properties
However I have multiple properties files (e.g. db.properties). I'm loading currently load this non-profile specific file as:
#Configuration
#PropertySource( {"classpath:db.properties"} )
class DataSourceConfig {
#Value("db.server") String server;
...
}
How can I combine these two things together, so it loads db-dev.properties like Spring Boot does for application.properties
It sounds like it should be easy, but I can't work out how to do it?!
Java -jar my-spring-boot.jar --spring.profiles.active=test you can set profile.active=your environment via commandline
I just saw that you use #PropertySource. The docs say:
Profile specific variants of both application.properties (or application.yml) and files referenced via #ConfigurationProperties are considered as files are loaded.

Resources