Tal Ben Shabtay
Tal Ben Shabtay

Reputation: 223

Resolving placeholder within @PropertySource

I'm trying to make a configuration class that will load application properties from a file using the @PropertySource annotation, but the PropertySourcesPlaceholderConfigurer doesnt seem to set the location received from the annotation.

@Configuration
@ComponentScan("com.just.a.test")
@PropertySources({
    @PropertySource(value="file:C:\\tmp\\1.cfg" 
            , ignoreResourceNotFound=true)
})
public class TestConfig {
    @Value("${just.a.string}")
    String justAString;


    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
       return propertySourcesPlaceholderConfigurer;
    }
}

the application property file is :

just.a.string=DOH

and im receiving the following exception :

.... Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'just.a.string' in string value "${just.a.string}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:801)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:955)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 15 more

how ever, if i am setting the location using the PropertySourcesPlaceholderConfigurer bean, everything works fine.

@Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setLocation(new FileSystemResource("c:\\tmp\\1.cfg"));
       return propertySourcesPlaceholderConfigurer;
    }

i am using Spring 4.1.6-RELEASE , and jdk 8.05.

thanks in advance.

UPDATE 1

as sivaprasadreddy.k mentioned. the code above does work fine, i forgot that in my original code i am retrieving the file out of a JVM param using the -

@PropertySource(value="file:#{systemProperties['config.path']}" 

and passing a jvm param of:

-Dconfig.path=C:\\tmp\\1.cfg

@Sotirios - im just using an AnnotationConfigApplicationContext(Class) like so -

public static void main(String[] args) { 
new AnnotationConfigApplicationContext(TestConfig.class);
 }

UPDATE 2

basically what im trying to achieve is this:

1) load a property file using a jvm param which its name defined as a const

a) if the file is found then proceed

b) else if a default file path which defined as a const exists then proceed

c) else proceed.

2) try to resolve @Value using a property which its name is defined as a const

a) if found proceed

b) else load a default value using a const.

sorry for the spaces. something is wrong with the editor.

Upvotes: 2

Views: 12187

Answers (2)

pramod Rajane
pramod Rajane

Reputation: 17

Trying adding @TestPropertySource(properties = {"targetEnv = test"}) ex. whichever env variable you want to inject.

Upvotes: -1

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279880

Considering your edit

@PropertySource(value="file:#{systemProperties['config.path']}" 

you have to first realize that the @Configuration class (and its annotations) is parsed and processed before the @Bean declared inside it. In other words, your PropertySourcesPlaceholderConfig (which does resolution of #{..} placeholders) has not been registered by the time Spring has processed the @PropertySource annotation. It's not available.

Instead, Spring can perform a subset of the behavior provided by a PropertySourcesPlaceholderConfig, only the ${..} placeholders. (See the javadoc.) And it can only use the property sources already registered with your ApplicationContext's Environment. In your examples, there are (should be) only two sources, the system properties and system environment.

The notation

systemProperties['config.path']

states: give me the value of the property config.path in the property source named systemProperties. I'm not sure in which order Spring checks the property sources named above, but if you know that only your system properties (and not the environment) has a config.path property, you can simply use

@PropertySources(value = { @PropertySource(value = "file:${config.path}") })

Upvotes: 3

Related Questions