Spring Boot configuration conventions - java

For Spring Boot app, we use application.yml or .properties variant to write spring-specific app configuration. For example:
server:
port: 7779
management:
endpoints:
web:
exposure:
include: gateway
Is there some convention how to name application domain-specific configuration? Where to put this config: in same application.yml or it should be separate file? How to name those properties? Example
adder-service:
max-number : 33
some-other:
a:
b: 44
Should we generate additionally META-INF/additional-spring-configuration-metadata.json for this app-specific config?

A good practice is to think about configuration file as about a configuration structures with defaults:
myapp:
myprop1: abc
myprop2: xyz
The actual values come from the environment:
MYAPP_MYPROP1=abc
MYAPP_MYPROP2=xyz
Use type-safe configuration in code with an application specific prefix.
#ConfigurationProperties("myapp")
class MyAppProperties {
private String myprop1;
private String myprop2;
// getters & setters ...
}
If the configuration is specific fo a particular deployment scenario, put it into a separate file managed by a Spring profile eg. application-aws.yml etc.
spring.profiles.active=aws

Related

Spring Boot: Load common config application properties file using bootstrap.yml

In our config server we have following application properties files:
helloApp-dev.properties //dev env properties
helloApp-commonConfig.properties //common properties across env
The properties are accessible from URI like:
https://myapp.abc.com/1234/helloApp-dev.properties
https://myapp.abc.com/1234/helloApp-commonConfig.properties
Below is our bootstrap.yml of helloApp application:
---
spring:
application:
name: helloApp
---
spring
profiles: dev
cloud:
config:
label: 1234
name: {spring.application.name}
uri: https://myapp.abc.com/
I am using Spring boot version 2.2.4. The helloApp-dev.properties are loading successfully in application but not commonConfig.
The configuration in commonConfig is not being loaded because you are not indicating to Spring that it should load that profile/config, because you are activating only the dev profile - and the configuration for that profile is the one which is being loaded:
---
spring
profiles: dev
In addition to the good solutions proposed by #akozintsov in his/her answer, if you need to include certain common configuration in different environments or profiles, let's say dev, qa or prod, you can use the spring.profiles.include configuration property and include, as a comma separated list of values, if using properties files, or as a list, if using yaml, the different common profiles and corresponding configurations you need to.
In your example, in helloApp-dev.properties you need to include the following information within the rest of your configuration:
spring.profiles.include=commonConfig
These related SO question and this article could be of help as well.
To load properties file, profiles should match.
You have 2 solutions:
Rename helloApp-commonConfig.properties -> helloApp.properties
Use multiple profiles for your application (dev, commonConfig)

#ConfigurationProperties usage in spring

I have a project built up on struts framework but I've integrated Spring Framework in same(using a servlet-config.xml) and using the MVC and AOP in it, now in one requirement I must use one project which is built up on SpringBoot and using #ConfigurationProperties binding an application.yml file with a POJO.
I just need to use the code of that project and hence added the dependency of that project. Is there any way I can use #ConfigurationProperties to bind the POJO with the yml file in my project. I tried but bean is not binding with the yml file entries.
As far as I know #ConfigurationPropertiesis part of SpringBoot features only.
Please give your useful suggestion.
You can do something like for example below:
if your yml file has properties containing same prefix then you could use as below:
POJO class:
#Configuration // add this if your spring boot version is < 2.2 or else please donot add.
#ConfigurationProperties(prefix = "spring.db.props") //example
public class MyPojoProps{
private String userName;
private int password;
private String uri;
// standard getters and setters
}
your application.yml may be something like below:
application.yml
spring:
db:
props:
userName:
password:
uri:
Please refer here for more information

How to resolve placeholder in properties file with values from another properties file in spring boot application

My spring boot application has below properties files.
src/main/resources/config/DEV/env.properties
mail.server=dev.mail.domain
src/main/resources/config/QA/env.properties
mail.server=qa.mail.domain
src/main/resources/config/common/env.properties
mail.url=${mail.server}/endpoint
Is it possible to load "common/env.properties" so that it's placeholders will be resolved using the given environment specific properties file. For DEV environment, we want the placeholders in "common/env.properties" to be resolved using values from "DEV/env.properties".
There are answers about how to load multiple properties files and profile based loading but could not find an answer for this particular use case.
Thanks in advance.
2 Options :
Generate the common/application.properties using configuration-maven-plugin and filter files for each environment. It is outdated now.
Use application-<env>.properties for each environment and pass the -Dspring.profiles.active=<env> as VM option in application start up. Spring will automatically take the property from correct file.
In option 2, you will be overwriting whatever is present in application.properties with application-.properties. So you dont have to add only the properties which you need to change per environment.
for eg:
Your application.properties can have
logging.level.root=WARN
logging.level.org.apache=WARN
logging.level.org.springframework=WARN
Your application-dev.properties can have
logging.level.org.springframework=DEBUG
which means, when you are starting application using dev profile, spring takes
logging.level.root=WARN
logging.level.org.apache=WARN
logging.level.org.springframework=DEBUG
edit :
Also, you can try something like below on your class. (Spring will overwrite value in config.properties with values from config-dev.properties). ignoreResourceNotFound will make sure, application will still start with default values even if the corresponding file is not found.
#Configuration
#PropertySource("classpath:config.properties")
#PropertySource(value = "classpath:config-${spring.profiles.active}.properties", ignoreResourceNotFound = true)
You can add resources/application.yml file where you can have multiple profiles in one File.
MultiProfile Yaml
e.g.here are two different profiles 'dev' and 'qa' with different applicationNames 'DEV' and 'QA' and one defaultName 'Default'
spring:
application:
name: Default
profiles:
active: qa
---
spring:
profiles: dev
application:
name: DEV
---
spring:
profiles: qa
application:
name: QA
You can achieve this by declaring a property source on a class configuration and setting up an environment variable in the path :
#PropertySource({ "classpath:config/${env}/env.properties" })
#Configuration
public class config{}
And then you launch the spring boot app with the command line variable -env=dev
UPDATE
You can use #PropertySources annotation to load several properties.
#PropertySources({
#PropertySource("classpath:config/${env}/env.properties"),
#PropertySource("classpath:config/common/env.properties")
})
public class config{}

Merge 2 files from starter and spring-boot app

in my project i have starter and spring-boot application with this starter.
Starter contains application.yaml file with few properties.
For example:
my:
test:
value: test
spring:
profiles:
active: development
i'm adding application.yaml file to my spring-boot app, and values from starter's yaml aren't injected to context.
My question,
how i can configure 2 yaml files in starter and application with option for override values with spring-boot app's starter, for example:
spring:
profiles:
active: testing
After merge i want to have:
spring.profiles.active=testing
my.test.value=test
Currently it's failed with error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'my.test.value' in value "${my.test.value}"
Use spring.profiles.include
spring:
profiles:
active: testing
include: default
Or you can create different application-profile.yml (for example application-testing.yml) and specify the profile while starting spring boot application
Command
java -jar name.jar spring.profiles.active=testing // it will pick the properties values from application-testing.yml
In the yml file use include to include any other profiles
application-testing.yml
spring:
profiles:
include: default
#Deadpool
One issue with override
I made application-starter.yaml in starter and include it in sprinng-boot with include.
my:
test:
value: spring--123
spring:
profiles:
active: development
include: starter
I injected with #Value
#Value("${my.test.value}")
private String testval;
and testval=test (from starter) Have i option for make values from application.yaml more primary?
thanks

How do I get multiple default values in properties across different profiles?

I have a few microservices with the same configuration, with each depending on a Spring profile. #ConfigurationProperties takes the values that I have in my YAML application profile file. I want to move this configuration to a common project and out of the microservices YAML configuration.
The problem is that I have 2 different configurations for different profiles. I can use #Value to inject default values, but I can do that only once. Is there a way to have multiple default values contingent on a specific Spring profile?
In my project we use Java configuration, not XML.
Do you mean like below ? I have two profiles A1 & B1 with the same property (app.port) in the same yml file (application.yml). The profiles are separated by ---
---
spring:
profiles: A1
app.port: 8080
---
spring:
profiles: B1
app.port: 9090
---
If you want to read properties from common location then write bootstrap.yml in your microservices and delete application.yml.
bootstrap.yml:
spring:
config:
location: file:/home/external/properties/location/
name: application
profiles:
active: dev
file location: /home/external/properties/location/
suppose you need dev and prod environment.Then keep this 3 properties file in this location.
application.yml
application-dev.yml
application-prod.yml
Spring boot read application.yml properties first. If set active profile dev in bootstrap.yml then application.yml value overwirte by application-dev.yml.
For different value just change active profile in bootstrap.yml of your microservices.
According to my search, I cannot resolve this issue as I want. Probably spring-cloud-config would resolve my problem but I don't want to implement this one. I changed the library and don't need to have these separate configs anymore.

Categories