javaspringmavenproperties-fileproperty-placeholder

How to resolve placeholder when run Spring based application?


Collegues, i have java based Spring config:

@Configuration
@EnableTransactionManagement
@ComponentScan (basePackages = {"com.abc.dirint"})
@PropertySource("classpath:/settings/${env}/dir.properties")
@EnableScheduling
public class DirConfig {

    private static final Logger log = LoggerFactory.getLogger(DirConfig.class);

    @Autowired
    private Environment environment;

     @Bean
        public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() throws IOException {
            PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
    propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
            return propertySourcesPlaceholderConfigurer;
        }


        /*Beans follow...*/ 

        }

When i execute mvn clean package -Denv=dev it run tests and build project without any error.

Now i would like to run compiled jar. I execute java -jar dir-integration-1.2-SNAPSHOT.jar -Denv=dev and the program fails (this is expected) with th next stacktrace:

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.abc.dirint.DirConfig]; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'env' in string value "classpath:/settings/${env}/dir.properties"
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:180)

Wnen i run $ java -jar dir-integration-1.2-SNAPSHOT.jar --env=dev the result is next:

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.abc.dirint.DirConfig]; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'env' in string value "classpath:/settings/${env}/dir.properties"
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:180)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
        at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
        at com.abc.dirint.AdApp.main(AdApp.java:19) Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'env' in string value "classpath:/settings/${env}/dir.properties"
        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:236)
        at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
        at org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders(AbstractEnvironment.java:571)
        at org.springframework.context.annotation.ConfigurationClassParser.processPropertySource(ConfigurationClassParser.java:379)
        at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:

What should I do to receive properties from the specified properties file during app running?


Solution

  • from java -h

    Usage: java [-options] class [args...]
               (to execute a class)
       or  java [-options] -jar jarfile [args...]
               (to execute a jar file)
    where options include:
    ...
        -D<name>=<value>
                      set a system property
    

    Therefore the correct command to run your jar with system property provided should be java -Denv=dev -jar dir-integration-1.2-SNAPSHOT.jar instead


    And, you should be aware that, using mvn ... -Denv=dev vs java -Denv=dev ... is two totally different thing.

    With mvn, placeholder replacement happens in compile time, which means the final jar will contains @PropertySource("classpath:/settings/dev/dir.properties")

    However, your 2nd approach is to keep the placeholder in compiled class, and rely on Spring to perform the replace in runtime