Spring boot, use profiles to load files - spring-boot

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.

Related

Quarkus #ConfigMapping: when no prefix defined, skip/ignore system and environment variables, only scan properties with defined keys

Some properties defined in my app are used by other applications in the same organization, so I cannot add a dedicated namespace before them to differentiate. While moving to Quarkus #ConfigMapping, I found Quarkus by default scans all system and environment variables as well as application scoped properties, and non-mapped properties will stop app from launching, showing a lot of "cannot find any root to map" error.
Quarkus YAML config is based on Smallrye config, which has:
smallrye.config.mapping.validate-unknown=false
to stop this behaviour.
https://smallrye.io/smallrye-config/2.11.1/config/mappings/#retrieval
For a Config Mapping to be valid, it needs to match every configuration property name contained in the Config under the specified prefix set in #ConfigMapping. This prevents unknown configuration properties in the Config. This behaviour can be disabled with the configuration smallrye.config.mapping.validate-unknown=false.

How to disable auto configuration when test profile in #SpringBootApplication?

Are there elegant ways to prevent AutoConfigure configuration classes when certain profile (e.g. test) in use? I've all configs in my tests, and don't wanna mark every config in main folder with #Profile("!test")
there also is: #SpringBootApplication(exclude=****Configuration.class) possibility but it's for class, not for profile.
What I did (but not for test) its to disable the AutoConfigure via properties file when a certain profile is enabled.
For instance, I don't want Redis to be auto-configured when profile "withoutRedis" is enabled (dev purpose).
I created a property file "application-withoutRedis.properties" and its content :
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

What is advantage of using #value annotation in Spring Boot

I am new to Spring Boot and I am doing code cleanup for my old Spring Boot application.
Below code is using #Value annotation to inject filed value from properties file.
#Value("${abc.local.configs.filepath}")
private String LOCAL_ABC_CONFIGS_XML_FILEPATH;
My doubt is instead of getting value from properties file, can we not directly hardcode the value in same java class variable?
Example: private String LOCAL_ABC_CONFIGS_XML_FILEPATH="/abc/config/abc.txt"
It would be easier for me to modify the values in future as it will be in same class.
What is advantage of reading from properties file, does it make the code decoupled ?
This technique is called as externalising configurations. You are absolutely right that you can have your constants defined in the very same class files. But, sometimes, your configurations are volatile or may change with respect to the environment being deployed to.
For Example:
Scene 1:
I have a variables for DB connection details which will change with the environment. Remember, you will create a build out of your application and deploy it first to Dev, then take same build to stage and finally to the production.
Having your configurations defined externally, helps you to pre-define them at environment level and have same build being deployed everywhere.
Scene 2:
You have already generated a build and deployed and found something was incorrect with the constants. Having those configurations externalised gives you a liberty to just override it on environment level and change without rebuilding your application.
To understand more about externalising techniques read: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Here #value is used for reading the values from properties file (it could be a any environment like dev, qa, prod) but we are writing #value on multiple fields it is not recomonded so thats instead of #value we can use #configurableProperties(prefix="somevalue>) and read the property values suppose `
#configurableProperties(prefix="somevalue")
class Foo{
string name;
string address;
}
application.properties:
somevalue.name="your name"
somevalue.address="your address"
`

Spring boot - expose common application properties with different names

I have a requirement where I need my custom application properties to act as aliases to various common application properties that spring provides for different packages.
Example:
Whenever I set a value to the application property foo.host, it should set the value for spring.rabbit.host property.
Similarly setting the value for foo.port should set the value for spring.rabbitmq.port.
Can this be achieved?
It can, you can add these to your application.properties:
spring.rabbit.host=${foo.host}
spring.rabbit.port=${foo.port}
However, if you still provide spring.rabbit.host via system properties, as an environment variable or as direct argument then it will take precedence over foo config.

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