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

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

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.

Multiple properties file for a single spring profile

We are using spring boot 2.0.0. We have three environments dev, staging, production. Our current config structure
dev
application-dev.yml
application-dev.properties
Likewise, we have a yml and properties file for each environment. After a year of development now the single yml file for a profile become a large monolithic config.
is it possible to have a multiple config files for a profile like below?
application-dev.yml
application-dev-sqs.yml
application-dev-redis.yml
I think there are 2 ways you can achieve this requirement.
spring.profiles.active accepts a comma-separated list of active profiles, so you can always provide dev,dev-sqs,dev-redis as the value.
Another approach is by making use of #PropertySource and a custom PropertySourceFactory to achieve this requirement. You can find an implementation which takes the value from spring.profiles.active to load one corresponding YAML file in the article below. It should be super easy to adapt the implementation to load multiple files by looking for the profile id in the name of the YAML files.
[How-to] Read profile-based YAML configurations with #PropertySource
I was dealing with a similar problem and I'd recommend using yaml configuration.
Let's describe .properties file:
Initital approach
One can use it like this:
#Component
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource("classpath:application-${spring.profiles.active}.properties")
})
public class AppProperties {
}
This is very easy to configure. Limitation is, that you cannot combine profiles. I mean, that when you want to use profile as dev,local where local just alters some config properties for dev profile, Spring will try to load application-dev,local.properties file, which is very likely not what you want.
Btw, this is what Spring will do for you automatically, this is useful for topics as you described.
There is no way to configure it per profile (and not for whole list). Other possibility would be, that one can specify the list in spring.config.name which is not the case at the moment.
Better approach
In short, use:
#Profile("dev")
#Configuration
#PropertySources({
#PropertySource("classpath:topic1-dev.properties"),
#PropertySource("classpath:topic2-dev.properties")
})
public class AppPropertiesDev {
}
Disadvantage is, you have to have several such config classes (dev, staging), but know you have the topics. Also you can use mutliple profiles, which are (as of my testing) loaded in order you specified. That way, your developer can easily use dev configuration and alter just what's needed for his/her testing.
Yaml approach
You can see the approach with yaml in question I asked earlier - Property resolving for multiple Spring profiles (yaml configuration), benefit is smaller amount of files - yaml has all the profiles in one file, which may or may not be what you want.
Yes, it's possible. spring.config.location is used to externalize the config file location in Spring boot applications. This can be used to provide a location of the file in the filesystem or even in the classpath. Based on how you want to provide your application access to the files, you can choose the URI.
Doing it programmatically:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(Application.class)
.properties("spring.config.location:classpath:/application-dev.yml,classpath:/application-dev-sqs.yml,classpath:/application-dev-redis.yml")
.build()
.run(args);
}
}
Doing it via environment variables:
set SPRING_CONFIG_LOCATION=classpath:/application-dev.yml, \
classpath:/application-dev-sqs.yml, \
classpath:/application-dev-redis.yml
So, you can provide your files as comma-separated values.
I've used classpath here, it can also be a location in the file system:
/home/springboot-app/properties/application-dev.yml,/home/springboot-app/properties/application-sqs.yml,/home/springboot-app/properties/application-redis.yml
Have you tried including profiles yet ?
Example with profile default, you want to load additional properties for redis and db. Within application.properties file, add:
spring.profiles.include=redis, db
This will load files application-redis.properties and application-db.properties respectively

Execute the same #SpringBootTest with different properties

I have a #SpringBootTest which is used to execute an integration test on the server. Depending on the configuration I want the server to behave differently. The configuration itself is read by beans (scope = singleton) deep inside my app logic and they read the property via #Value annotation.
How could I execute the same test with different configuration settings? I have tried to write different test classes and annotate them with #TestPropertySource(properties = XYZ). But it seems that this affects all other tests as well (due to the singleton scope?). It there a way to reset the properties after the test?
To respecify my problem: I want to configure my bean with a different #Value property during my tests and this value should only be valid throughout this specific test execution.
Thanks ahead for any pointers.
I have a webservice, which is connecting to the client of other webservice by using property from the config. As in any organization, we have different environments. For testing, I wanted to hit testing env instead of local. This is how I override the default property value only for integration test. By doing this, I can hit the test env instead of default local env.
#SpringBootTest(value = {"eureka.client.enabled=false", // Don't start Eureka
"com.somepackage.webservicename.client.serviceUrl = http://nodename.envname:26730"})
Hope this helps!

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 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