How to replace properties files by yml files in Spring boot - java

Is there anything special to say to Springboot to take in account as configuration yaml files instead the properties files? I'm using Maven and Springboot in a project, if I place the file application.properties in the resources file the configuration is automatically recognised by Springboot.
However just replacing the properties file by a yml file does not work, the file is not taking in account anymore.
Anything to add to splicitely say to SpringBoot to use the yml files?
Below both files:
application.properties:
# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.check-template-location=true
spring.thymeleaf.prefix=/WEB-INF/views/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
and application.yml
spring:
profiles:
active: ${dario.environment:dev}
thymeleaf:
check-template-location: true
thymeleaf.prefix: /WEB-INF/views/
thymeleaf.suffix: .html
thymeleaf.mode: LEGACYHTML5
spring.thymeleaf.encoding: UTF-8
spring.thymeleaf.content-type: text/html
cache: false

If you refer to the section 'Using YAML instead of Properties' in the Spring Boot reference documentation, it says that Spring Boot should pick it up automatically given you have the SnakeYAML library on your classpath.
Having that said, it also states
If you use ‘starter POMs’ SnakeYAML will be automatically provided via
spring-boot-starter

Related

Spring Boot not working with dependent application.properties

I'm working with the Spring Boot 2.2.9.RELEASE. I have the main app and some plain starter (which just uses spring-actuator functionality) with some properties in its some-starter/src/main/resources/application.properties file:
management.server.port=9000
management.server.ssl.enabled=false
management.endpoints.enabled-by-default=false
management.endpoint.health.enabled=true
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=health
I've imported the starter into my main app and I believe that the healthcheck endpoint should work with the port 9000 and with the path /health (smth like that localhost:9000/health).
But it doesn't. However, it works in case of the same properties in my main app main-app/src/main/resources/application.properties.
Is it problem with the property overriding in Spring Boot? Should i configure my resources via something like maven-resources-plugin?
When application.properties is loaded from the classpath, the first one on the classpath is loaded and any others on the classpath are ignored. In your case, the file in main-app/src/main/resources/application.properties will appear on the classpath before the application.properties in the jar of some-starter.
As its name suggests, application.properties is intended for configuring your application and it shouldn't be used in a starter. You should either configure all of the properties in your application, or you could update your starter to include an EnvironmentPostProcessor that is registered via spring.factories and adds some default properties to the Environment.

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

Can we use multiple yaml files in a single spring boot application?

I have one yaml file that reads all the environment profiles. I need another yaml file to create a feature switch that i can turn on/off during deployment. And how can we define the feature switch in properties file.
Yes, you can use multiple YAML files if you use spring profile. For example, if you start your JVM with the following flag:
-Dspring.profiles.active=deployed,cassandra
It will pick up the following application YAML files:
application.yml, application-deployed.yml, and application-cassandra.yml
Another way to do this, is by adding this key in the application.yml file like below
spring:
profiles:
include:
- student
- address
and you can name your yaml files, as
application-student.yml, application-address.yml

spring yml file for specific environment

I have 3 yml files namely
application-default.yml -> default properties, should be available
in all profiles
application-dev.yml -> properties only for dev
profile
application-prod.yml -> properties only for prod profile
When I start my boot application by passing the -Dspring.profiles.active=dev,I am able to access the application-dev.yml specific properties.
But I cant get the properties defined in the application-default.yml files.
Following is my application-dev.yml file:
Spring:
profiles:
include: default
spring.profiles: dev
prop:
key:value
TL;DR
Just rename the application-default.yml file to application.yml and will work as you expect.
Explanation
According to the description in the docs, a file called application-{suffix}.yml is activated when you run your application with the profile which name matches with the suffix. In addition, the main application.yml is loaded by default so it's the perfect place to put common properties for all profiles. Alternatively, if you want to keep the name of your file as application-default.yml you can pass two profiles to your Spring Boot application:
-Dspring.profiles.active=default,dev
This way you will activate two profiles and both properties files will be loaded.
I was able to solve my problem, here is what I did.
Created a file application-common.yml, put the common properties there.
Then in the application-{env}.yml files I put this on the top.
spring:
profiles:
include: default
Since I dont need to ever load the default profile specifically, this works for me!!!
What I do is:
Put common settings in application.xml, and in this file add:
spring:
profiles:
active: dev, pro, xxx...
all the profiles you want to activate.
So that you just edit this file to switch environment.
Remember that external files procedes, so you can leave another application.xml outside of the WAR to activate dev/pro/... environment instead of editing this file every time. Be sure to check the documentation:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

how can I access system properties using spring boot and Liquibase changeset yaml file

A Spring Boot Java application using Liquibase to manage the database schema changes is started with a parameter (e.g. dev, int) specifying the environment it runs in.
There are corresponding properties files (e.g. dev.properties, int.properties) which define properties for the corresponding environment.
So in dev.properties there is e.g.
url.info=http://dev.app.info
and in tst.properties there is
url.info=http://tst.app.info
The application reads in the properties from the file corresponding to the passed in parameter.
This mechanism works fine when the application is deployed and started in each environment. There are many instances when the corresponding property is used.
However, it doesn't work with a Liquibase yaml changeset containing the following insert statement
- insert:
tableName: result
columns:
- column:
name: id
value: a88b6708-5c9f-40c4-a3ca-41e7a6b57fc8
- column:
name: infoUrl
value: ${url.info}
I have tried double and single quotes in the yaml file, i.e. "${url.info}" and '${url.info}' but the database always ends up with the String ${url.info}
Is there another notation I have to use for properties in yaml files?
or
Can properties not be referenced in liquibase yaml files the way they can with xml files?
As you are using Spring Boot, you can use its application.properties file to define change log parameters.
Any property with a name that begins with liquibase.parameters. can be referenced in a changelog. For example, the property liquibase.parameters.url.info can be referenced as ${url.info} in your changelog (YAML or XML).
To use different configuration files for dev, QA, production etc you can use profiles and profile-specific configuration files. For example, the application-dev.properties file will only be loaded when the dev profile is active.
Thanks Any from answer above.
Just to make it clearer: your full param name in your application.yaml should look like:
spring:
liquibase:
parameters:
paramName: paramValue
And then you can refer it in liquibase changeset as ${paramName} in my case

Categories