Reputation: 9967
I'm trying to use the Spring framework's @PropertySource
annotation in a Jar to load a properties file from outside the jar, but it's not finding the file.
I need the properties file to be external to the Jar so it can be edited. I don't know the exact location where the file will be, I figured I could just have it anywhere on the classpath.
I'm using the following annotation on my Config
class.
@PropertySource('classpath:stc.properties')
And placed stc.properties
in the same directory as the created Jar file. I tried specifying the classpath explicitly in the java
command, but it still cannot find the file:
java -cp . -jar stc.jar
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load bean class: com.example.stc.Config; nested exception is java.io.FileNotFoundException: class path resource [stc.properties] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:162)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:299)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:609)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
[...]
Etc.
I've also tried using ./
as the classpath, and tried specifying the classpath (with both variants) in the Class-Path
attribute of the jar's manifest, but it always gives the same results.
Upvotes: 14
Views: 43387
Reputation: 10818
Let's say you have a jar with a default main and some default stc.properties
inside the classpath.
An option would be that if there is a configuration file with that name next to the jar (actually in the execution directory) the properties that are set inside that config are merged with the ones of default config.
If the user decides not to use the external config, no error occurs.
For the above scenario you need:
@PropertySources({
@PropertySource("classpath:stc.properties"),
@PropertySource(value = "file:./stc.properties", ignoreResourceNotFound = true)
})
e.g. let's say the default stc.properties
(inside the jar) content is:
propA=valueA
propB=valueB
Now if I add a file with the same name next to the jar containing:
propB=updatedValueB
propC=valueC
The effective loaded properties when executing java -jar stc.jar
are:
propA=valueA
propB=updatedValueB
propC=valueC
Upvotes: 1
Reputation: 515
Use a variable (System or Environment) to have the value of the file and you could refer your file like this:
@PropertySource("file:${MY_PATH}/application.properties")
Upvotes: 14
Reputation: 6749
Assuming you have two files, one for local one for production
@PropertySources({
@PropertySource("classpath:application.properties"),
@PropertySource(value = "${ws.properties}", ignoreResourceNotFound = true)
})
And in tomcat or your jar file , pass on this parameter
-Dws.properties=file:/path-to.properties
I added this in setenv.sh
APPLICATION_OPTS="-Dlog4j.configurationFile=file:$PATH/log4j2.xml -Dlog4j.debug=true -Dapplication.properties=file:$PATH/application.properties
This is possible with Spring 4 only
Upvotes: 18
Reputation: 5425
My environment was:
OS: Windows | Container: Tomcat | Java: 7 | Spring: 4.2.4 | Springboot 1.3.1 | Maven
Step 1 a (war):
Add the file externalised properties file to JVM system properties.
As am running this off tomcat; I done this by creating setenv.bat in <TOMCAT_HOME>/bin/setenv.bat
set CATALINA_OPTS=%CATALINA_OPTS% -Dexternal.app.properties=file:<PATH_TO_EXTERNAL_FILE>\application-prod.properties
Step 1 b (jar):
Alternative if you are running from a jar use:
-Dexternal.app.properties=file:<PATH_TO_EXTERNAL_FILE>\application-prod.properties
Note the use of file: at the start on the line.
Step 2: In my application startup class I used annotation @PropertySource
to load the specific environment application properties.
@SpringBootApplication
@PropertySources({
@PropertySource(value = "${external.app.properties.file}", ignoreResourceNotFound = true),
@PropertySource(value = "classpath:application.properties")
})
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
Step 3:
Using externalised properties in project
external/file/path/application-prod.properties
spring.datasource.url.ext=< PRODUCTION_DATASOURCE >
/src/main/resources/application.properties
spring.datasource.url=${spring.datasource.url.ext}
Hope this helps other having the same problem.
Upvotes: 3
Reputation: 1
you could use --spring.config.location=file:/somepath parameter when running jar, where you specify path to config file (could be relative).
More info in docs
Upvotes: 0
Reputation: 114
try giving the full path of the file:
@PropertySource('file:c:/.../stc.properties')
Upvotes: 0