I'm using spring boot and application.properties
to select a database during development by @Configuration @Profile("dev")
.
spring.profiles.active=dev
spring.config.location=file:d:/application.properties
During production I'd like to create a file outside of the application context that should be loaded and then active a different configuration profile, with d:/application.properties:
spring.profiles.active=production
Result: when I start the app, the configuration is still dev
, so somehow the additional location of the productive properties file is not taken into account. Am I missing anything?
spring boot 1.1.0.BUILD-SNAPSHOT
Note: this question is NOT about tomcat.
spring.config.location
can only be set from the command-line and not from within a properties file.
application.properties
files located in other directories of your project?
I know you asked how to do this, but the answer is you should not do this.
Instead, have a application.properties
, application-default.properties
application-dev.properties
etc., and switch profiles via args to the JVM: e.g. -Dspring.profiles.active=dev
You can also override some things at test time using @TestPropertySource
Ideally everything should be in source control so that there are no surprises e.g. How do you know what properties are sitting there in your server location, and which ones are missing? What happens if developers introduce new things?
Spring Boot is already giving you enough ways to do this right.
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
You can also use @PropertySources
@PropertySources({
@PropertySource(value = "classpath:application.properties"),
@PropertySource(value = "file:/user/home/external.properties", ignoreResourceNotFound = true)
})
public class Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
}
application.properties
(at least in Spring ver. 4.3.20) It seems Spring 4 has a bug that prevents overriding. Just rename application.properties
-> app.properties
and all would be fine.
I am not sure you can dynamically change profiles.
Why not just have an internal properties file with the spring.config.location property set to your desired outside location, and the properties file at that location (outside the jar) have the spring.profiles.active property set?
Better yet, have an internal properties file, specific to dev profile (has spring.profiles.active=dev) and leave it like that, and when you want to deploy in production, specify a new location for your properties file, which has spring.profiles.active=prod:
java -jar myjar.jar --spring.config.location=D:\wherever\application.properties
application.properties
file defining spring.config.location
and spring.profiles.active=dev
and override external. But does not work...
public static void main(final String[] args) { SpringApplication.run(Application.class, args);}
From Spring Boot 2, you will have to use
--spring.config.additional-location=production.properties
Update with Spring Boot 2.2.2.Release.
Full example here, https://www.surasint.com/spring-boot-override-property-example/
Assume that, in your jar file, you have the application.properties which have these two line:
server.servlet.context-path=/test
server.port=8081
Then, in production, you want to override the server.port=8888 but you don't want to override the other properties.
First you create another file, ex override.properties and have online this line:
server.port=8888
Then you can start the jar like this
java -jar spring-boot-1.0-SNAPSHOT.jar --spring.config.location=classpath:application.properties,/opt/somewhere/override.properties
UPDATE: this is a bug in spring see here
the application properties outside of your jar must be in one of the following places, then everything should work.
21.2 Application property files
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:
A /config subdir of the current directory.
The current directory
A classpath /config package
The classpath root
so e.g. this should work, when you dont want to specify cmd line args and you dont use spring.config.location in your base app.props:
d:\yourExecutable.jar
d:\application.properties
or
d:\yourExecutable.jar
d:\config\application.properties
see spring external config doc
Update: you may use \@Configuration together with \@PropertySource. according to the doc here you can specify resources anywhere. you should just be careful, when which config is loaded to make sure your production one wins.
config
dir outside the deployed war app? Because, when I redeploy the app, any created subfolders will be lost.
I have found the following has worked for me:
java -jar my-awesome-java-prog.jar --spring.config.location=file:/path-to-config-dir/
with file:
added.
LATE EDIT
Of course, this command line is never run as it is in production.
Rather I have
[possibly several layers of] shell scripts in source control with place holders for all parts of the command that could change (name of the jar, path to config...)
ansible deployment scripts that will deploy the shell scripts and replace the place holders by the actual value.
The spring configuration precedence is as follows.
ServletConfig init Parameter ServletContext init parameter JNDI attributes System.getProperties()
So your configuration will be overridden at the command-line if you wish to do that. But the recommendation is to avoid overriding, though you can use multiple profiles.
Success story sharing
spring.profiles.active=production
when running the jar/war. So i'm going to accept your answer.application.properties
run if profile is set toproduction
?