how to use Spring-EL in @Value when using constants to resolve a property

12,490

Solution 1

What about the simplest approach:

@Value("${" + InternalConstant.JOB_NAME_PROPERTY + "}")
private String jobName

Solution 2

You can access the property referenced by the constant using environment directly in the SpEL expression and the correct value should be injected:

@Value("#{environment.getProperty(T(com.example.InternalConstants).JOB_NAME_PROPERTY)}")
private String jobName;
Share:
12,490
Hansjoerg Wingeier
Author by

Hansjoerg Wingeier

Senior Java Software Developer Spring, SpringBatch, SpringBoot JEE

Updated on June 10, 2022

Comments

  • Hansjoerg Wingeier
    Hansjoerg Wingeier almost 2 years

    I'm trying to use a constant to define a property and then resolving it with the @Value annotation.

    I defined the constant in an interface:

    public interface InternalConstant{
       public static final String JOB_NAME_PROPERTY = "javabatch.jobName";
    }
    

    I'm using springboot and I'm adding the property as a default property to the context:

    SpringApplication springApp = new SpringApplication(configs.toArray());
    Properties props = new Properties();
    props.setProperty(InternalConstants.JOB_NAME_PROPERTY, "MyStartableJob");
    springApp.setDefaultProperties(props);
    

    Now, I'd like to use @Value to inject the String "MyStartableJob" into a String. But instead of directly using @Value(value="${javabatch.jobName}), I'd like to use the defined constant.

    I tried

    @Value(value="#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}")
    

    But of course, this resolves only to "javabatch.jobName" and not to the value of the property named "javabatch.jobName".

    So I tried to wrap it in @Value(value="${#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}}"), but this causes an exception.

    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder '#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}' in string value "${#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}}"
        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)
        ... 16 more
    

    I know, that I could simply inject the Environment and using its getProperty method:

    @Autowired
    private Environment env;
    
    public void m1() {
        env.getProperty(InternalConstants.JOB_NAME_PROPERTY);
    }
    

    This works and serves my purpose. But I wonder, if this could also be done using SPEL in @Value.

    Thanks.

    • Jens
      Jens almost 9 years
      Show the stacktrace please.
    • Hansjoerg Wingeier
      Hansjoerg Wingeier almost 9 years
      @Jens: I added the stacktrace
  • Bohuslav Burghardt
    Bohuslav Burghardt almost 9 years
    +1 for keeping things simple. This solution also has the added benefit that rename refactoring won't break your code in less intelligent IDEs :).
  • Gilles Bodart
    Gilles Bodart over 6 years
    But it's not going into a class constant to use for exemple in another annotation like caching group name ...
  • ASten
    ASten almost 6 years
    IDEA tells me, that "attribute value must be constant" although I have a String constant as a concatenated param...