简体   繁体   中英

@PropertySource in a Jar for an external file on the classpath

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.

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

使用变量(系统或环境)来获取文件的值,您可以像这样引用您的文件:

@PropertySource("file:${MY_PATH}/application.properties")

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.

尝试给出文件的完整路径:

@PropertySource('file:c:/.../stc.properties')

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

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)

})

eg 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM