Is there a way to include properties file in another properties file? - spring

I'd like to avoid cluttering the application.properties file with lots of things than, in my opinion, would be better in a separate file.
application.properties should be something like
#include module1.properties
#include module1.properties
...
###################################
######### Spring Misc #############
###################################
# Direct log to a log file
logging.file=/tmp/kmp-manager.log
#local listening port
server.port=8082
spring.profiles=nr_dev nr_testing production
spring.profiles.active=production
spring.datasource.platform=postgresql
java.security.egd=file:/dev/./urandom
Is this at all possibile?
If not, what would be a sane way to avoid cluttering?

Spring Boot Spring Boot 2.4 has added a feature for importing
We can now use spring.config.import=developer.properties to import other file. Check this blog post for more details

It's possible in YML file and the configuration are very simple
EXAMPLE:
To include properties of application-DATABASE.yml file in application.yml, use
spring:
profiles:
include: DATABASE
[EDIT - for 2.4.0 and above]
spring.profiles.group.prod=DATABASE
OR
Add the file name in application.properties
spring.config.import=classpath:application-DEV.yml,classpath:application-UDEV.yml,classpath:application-PRO.yml,classpath:application-SBA.yml

spring.config.import: file:${CLOUDJAVA_ROOT}/config/application.yaml
Imports are processed as they are discovered, and are treated as additional documents inserted immediately below the one that declares the import. Values from the imported file will take precedence over the file that triggered the import.
See spring-boot docs: Importing Additional Data

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",....}

Spring Boot yml file read order

I have below files under resources folder in a standard Spring Boot app .
Spring.active.profile is set to dev
In which order the properties files are read .?
1)application.yml
2)bootstrap.yml
3)application_dev.yml
4)bootstrap_dev.yml
As Spring doc mentions
Profile specific properties are loaded from the same locations as
standard application.properties, with profiles specific files
overriding the default ones
This would mean that first the application.yml is read and then the application_dev.yml is read and overrides values from the default application.yml if needed.
Same for bootstrap.yml and bootstrap-dev.yml
Also as you can see here
bootstrap.yml is loaded before application.yml.
So to answer your question the order should be
bootstrap.yml
bootstrap_dev.yml
application.yml
application_dev.yml
bootstrap files are always the first: bootstrap.yml then bootstrap-{profile}.yml. then application.yml and application-{profile}.yml.
the property values are overridden by the next files so:
a: 1 from application.yml will be overridden by a: 55 from application-{profile}.yml

Spring, Skipped (empty) config file

I'm running spring in debug mode, and after struggling to get it to recognize an external properties file I finally got it to do so
Loaded config file 'file:C:/Users/udyj/git/hermes-mq-tool.lib/rte/application-ALD-INT.properties'
However right after that line
Skipped (empty) config file 'file:C:/Users/udyj/git/hermes-mq-tool.lib/rte/application-ALD-INT.properties'
The thing is though, it isn't empty
Name=ALD-INT
Queues=
QueueManager=whatever
TAS_MQS_PASSWORD=pw
TAS_MQS_USER=name
I'm running spring this way,
pb = new ProcessBuilder().inheritIO().command(java, "-noverify", "-cp", classpath,
String.format("-Dspring.config.location=%s", "C:\\Users\\udyj\\git\\hermes-mq-tool.lib\\rte\\application-ALD-INT.properties"),
clazz.getCanonicalName()
);
What does the empty config file thing mean?
This is an open issue
The misleading logging is an unfortunate side-effect of it being
performed in a generic location that doesn't (and shouldn't)
understand the difference between .properties and .yaml configuration
files.

How to parameterize the search-locations path to be reusable in other config files

I have different files (yml & xml files) where I'm hardcoding the same folder path containing my configuration files. I want to parameterize this path, so I can be able to move my configuration and modifying my parameter only once.
My bootstrap.yml :
...
cloud:
config:
failFast: true
server:
bootstrap: true
prefix: /config
native:
search-locations: file:///C:/dev/workspace/application/config/{profile}
My application-dev.yml :
...
logging:
config: file:///C:/dev/workspace/application/config/{profile}/log4j2-dev.xml
My integration-config.xml :
<context:property-placeholder location="file:///C:/dev/workspace/application/config/${spring.profiles.active}/application-${spring.profiles.active}.properties" />
How can I achieve that ? What's the best practice in this case ? Or is it even good practice to parameterize the search-locations path for the Spring Config Server File System ?
First say I'm almost not use configuration file (yml properties xml...) directly in local-file-system(outside classpath) even for local test. And for spring-cloud-config what if you using remote location to contains config, question may different.
Second, did you using some project manager tool like maven or gradle? as maven is the default tool for spring-boot projects' build in my mind. And for maven there has plugin like Maven Resources Plugin to parameterize your config variable to pom.xml which can help you modifying parameter only once for all variable in one file in build step, and same as gradle.
For spring-cloud-config, it is possible to move your almost all configuration properties to it. Means that you can move your config properties from application-dev.yml and integration-config.xml to spring-cloud-config's config file which in your case is file:///C:/dev/workspace/application/config/{profile} and it will load as env variables in runtime for spring autoconfigure or which you can #Autowired to your Environment what if you want get it manually.

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

Resources