how to migrate spring.profiles.includes to spring boot 2.4 - spring

I have a git repository that containes properties files in this way :
application.properties file
APPNAME-profile.properties files
the application.properties contains common properties.
the APPNAME-profile.properties ( appname = spring.application.name ), the profile is defined when running the app by setting the property : spring.cloud.config.profile.
inside each APPNAME-profile.properties contains "spring.profiles.include=test" that define profiles that will be loaded. profiles are defined using #Profile annotation.
The issue I'm facing is when I tried to migrate to 2.4.0 the official doc suggest using group profiles and that what i dit but it's not loading the corresponding profiles
in each APPNAME-profile.properties file I have defined :
spring.profiles.group.admin-prod=client,tools,index
When running the app :
java -jar -Dspring.cloud.config.label=master -Dspring.cloud.config.profile=administration -Dspring.cloud.bootstrap.enabled=true -Dspring.profiles.active=admin-prod solution.war
the profiles defined in the spring.profiles.group.admin-prod are not loaded .

Related

Spring boot read map from .properities file

I have .properties file witch are values for a map of type
AF:Afghanistan
AL:Albania
DZ:Algeria
AS:American Samoa
AD:Andorra
AO:Angola
AI:Anguilla
the properties file has a name countries.properties so its not the application.properties one i have tried a lot of things but nothing seems to work.The java code is this
#Value("#{${}}")
private Map<String, String> countryOptions;
The annotaion is intenionaly left blank.
How can i make it load from the countries.properties?
If you're using a version prior to SpringBoot 2.4.0, Spring Boot allows including additional configuration files using the spring.config.location and spring.config.additional-location properties defined in application.properties file.
After Spring Boot 2.4.0, a new property called spring.config.import has been introduced which supports multiple features:
Adding several files or directories
Files can be loaded either from the classpath or from an external directory
Indicating if the startup process should fail if a file is not found, or if it's an optional file
Importing extensionless files
Example:
# Case 1
spring.config.import=classpath:additional-application.properties
# Case 2
spring.config.import=classpath:additional-application[.yml]
# Case 3
spring.config.import=optional:file:./external.properties
# Case 4
spring.config.import=classpath:additional-application-properties
i found a solution using #PropertySource("classpath:countryOptions.properties")
#Value("#{${countryOptions}}")
and at countryOptions.properties i changed the map to `countryOptions={"US":"United States",....}

custom yaml configuration files in a config folder outside the project (Spring)

I have a project with some config files. I need to externalize them to allow the user to edit them. It's a spring boot application and my files are in a yaml format.
It's not application.yaml, it's some custom files with different names.
I use bean annotations. For example, one of my beans looks like this :
#Configuration
#ConfigurationProperties
#PropertySource(value="globalConfiguration.yaml", factory = YamlPropertySourceFactory.class)
public class GlobalConfiguration {
//some fields
//accessors
}
When the file is in src/main/resources, it works well but once built it reads the file inside the jar (which is normal)
What I would like to do is to read in priority the yaml file from a config folder which is near the lib folder like this :
- bin
- config
globalConfiguration.yaml
- lib
myApp.jar
I tried using the parameter --spring.config.location="classpath:./config/" (and /./config and ././config and /config and config...) but nothing work I have this error :
***************************
APPLICATION FAILED TO START
***************************
Description:
Config data location 'classpath:/./config/' does not exist
Action:
Check that the value 'classpath:./config/' is correct, or prefix it with 'optional:'
EDIT :
Now I tried to add my config files to the classpath like this :
set CLASSPATH=%APP_HOME%\config\*;%APP_HOME%\lib\myJar.jar;someDepencies.jar
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %MYAPP_OPTS% -classpath "%CLASSPATH%" my.Main.Class %*
It's the bat generated by gradle when I build the project so I just added %APP_HOME%\config\*; to the classpath variable.
But it didn't change anything.
Finally it had nothing to do with the classpath. the spring.config.location works perfectly well but the directory used is the current one when launching the bat and my app was on a windows shared folder so I wasn't able to do a cd \mysharedfolder.. .
To make it works, there was two option :
To move the app in a local folder. Then move to the folder of the app and so the relative path works from there.
The second option is to set the complete path of the config folder like this :
--spring.config.location="\\\\mysharedfolder\\someSubDirectories\\config\\"

How to add profile specific properties files when I have custom name to my property file

I have properties file with name : transactionexpiry.properties in my project's src/main/resources folder.
I am able to read the properties in the code with #PropertySource("classpath:/transactionexpiry.properties")
Now I wan't to add application scope and add environment specific config files as transactionexpiry-dev.properties, transactionexpiry-local.properties, etc
But the same works with application.properties, application-dev.properties, application-local.properties
Is there a way to make it work with my previous set-up?
If you are using spring profiles:
-Dspring.profiles.active=dev
Then you can call the properties file like:
#PropertySource("classpath:/transactionexpiry${spring.profiles.active}.properties")

Spring boot on Tomcat with external configuration

I can't find an answer to this question on stackoverflow hence im asking here so I could get some ideas.
I have a Spring Boot application that I have deployed as a war package on Tomcat 8. I followed this guide Create a deployable war file which seems to work just fine.
However the issue I am currently having is being able to externalize the configuration so I can manage the configuration as puppet templates.
In the project what I have is,
src/main/resources
-- config/application.yml
-- config/application.dev.yml
-- config/application.prod.yml
-- logback-spring.yml
So how can I possibly load config/application.dev.yml and config/application.prod.yml externally and still keep config/application.yml ? (contains default properties including spring.application.name)
I have read that the configuration is load in this order,
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
Hence I tried to load the configuration files from /opt/apache-tomcat/lib to no avail.
What worked so far
Loading via export CATALINA_OPTS="-Dspring.config.location=/opt/apache-tomcat/lib/application.dev.yml"
however what I would like to know is,
Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.
And is there a better method to achieve this ?
You are correct about load order. According to Spring boot documentation
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).
[Note]
You can also use YAML ('.yml') files as an alternative to '.properties'.
This means that if you place your application.yml file to /opt/apache-tomcat/lib or /opt/apache-tomcat/lib/config it will get loaded.
Find out why loading via /opt/apache-tomcat/lib classpath doesn't work.
However, if you place application.dev.yml to that path, it will not be loaded because application.dev.yml is not filename Spring is looking for. If you want Spring to read that file as well, you need to give it as option
--spring.config.name=application.dev or -Dspring.config.name=application.dev.
But I do not suggest this method.
And is there a better method to achieve this ?
Yes. Use Spring profile-specific properties. You can rename your files from application.dev.yml to application-dev.yml, and give -Dspring.profiles.active=dev option. Spring will read both application-dev.yml and application.yml files, and profile specific configuration will overwrite default configuration.
I would suggest adding -Dspring.profiles.active=dev (or prod) to CATALINA_OPTS on each corresponding server/tomcat instance.
I have finally simplified solution for reading custom properties from external location i.e outside of the spring boot project. Please refer to below steps.
Note: This Solution created and executed windows.Few commands and folders naming convention may vary if you are deploying application on other operating system like Linux..etc.
1. Create a folder in suitable drive.
eg: D:/boot-ext-config
2. Create a .properties file in above created folder with relevant property key/values and name it as you wish.I created dev.properties for testing purpose.
eg :D:/boot-ext-config/dev.properties
sample values:
dev.hostname=www.example.com
3. Create a java class in your application as below
------------------------------------------------------
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
#PropertySource("classpath:dev.properties")
#ConfigurationProperties("dev")
public class ConfigProperties {
private String hostname;
//setters and getters
}
--------------------------------------------
4. Add #EnableConfigurationProperties(ConfigProperties.class) to SpringBootApplication as below
--------------------------------------------
#SpringBootApplication
#EnableConfigurationProperties(ConfigProperties.class)
public class RestClientApplication {
public static void main(String[] args) {
SpringApplication.run(RestClientApplication.class, args);
}
}
---------------------------------------------------------
5. In Controller classes we can inject the instance using #Autowired and fetch properties
#Autowired
private ConfigProperties configProperties;
and access properties using getter method
System.out.println("**********hostName******+configProperties.getHostName());
Build your spring boot maven project and run the below command to start application.
-> set SPRING_CONFIG_LOCATION=<path to your properties file>
->java -jar app-name.jar

How can I suppress the default config location of Spring boot

How can I have Spring Boot only look for config files under the the directories specified by spring.config.location property and not look under the default location as specified in the ConfigFileApplicationListener javadoc.
Setting spring.config.location, causes the ConfigFileApplicationListener to look in both spring.config.location directories and the default locations.
you can use profiles.
in your application.properties you will only have :
spring.profiles.active=other
and have a file in the same folder named application-other.properties where you define your properties.
the default properties can be in a file named application-default.properties and when you want to use it, juste change the value in application.properties to 'default'.
Spring-boot documentation of Profiles

Resources