5

I am trying to define the following property in one of my .properties files:

personExpression=${person.surname}

This is then read by a config class:

@Configuration
public class TemplateConfig {
    @Autowired
    private Environment environment;

    public String getPersonExpression() {
        return environment.getProperty("personExpression");
    }
}

However this gives the exception:

java.lang.IllegalArgumentException: Could not resolve placeholder 'person.surname' in string value "${person.surname}"

Is there a way to do get getPersonExpression() to return the string literal ${person.surname} without attempting to resolve it?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
IgorK
  • 55
  • 1
  • 4

3 Answers3

2

To get this to work takes some pretty unintuitive syntax.

You essentially have to split your expression into two parts and wrap the whole thing in a parent SpEL expression to join them.

If you change your property value to the following it should work:

personExpression=#{'$' + '{person.surname}'}

This works because you're splitting up the $ character from the {person.surname} so SpEL won't try to evaluate it as an expression, because as far as it's concerned, you're just concatenating two strings together.

JamesENL
  • 6,400
  • 6
  • 39
  • 64
  • Is there some additional configuration that needs to be added to get spring to evaluade expressions inside #{..}? I tried changing the property to `#{'$' + '{person.surname}'}` but `getPersonExpression()` just returns `#{'$' + '{person.surname}'}` – IgorK Jan 04 '16 at 05:33
  • Are you using a `PropertyPlaceholderConfigurer` bean? That should read your properties file, parse the values, and then make them available. If you aren't, then the properties file won't be parsed using SpEL. – JamesENL Jan 04 '16 at 06:06
  • Yep this was the issue. I had no `PropertyPlaceholderConfigurer` bean registered as there were no other properties that were being evaluated. Adding in `@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }` did the trick. Also I messed around with the formatting a bit and changed the property to `personExpression=#{'$'}{person.surname}` which still works and is a bit easier to read – IgorK Jan 04 '16 at 22:49
  • 1
    Additionally it looks like it only works if the property is retrieved using `@Value("${personExpression}")`. `environment.getProperty("personExpression")` just returns `#{'$'}{person.surname}` without evaluating it – IgorK Jan 04 '16 at 23:04
1

I don't know of any getRawPropertyValue type method that's accessible through the ApplicationContext.

If you know the name of your PropertySource, eg. example, you can get the ConfigurableEnvironment, and its registered PropertySources, retrieve the appropriate one, and get the required property value.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Sample.class);
ConfigurableEnvironment configurableEnvironment = ctx.getEnvironment();
String rawValue = configurableEnvironment.getPropertySources()
                       .get("example") // get property source
                       .getProperty("personExpression"); // get property

The variable rawValue will have the value ${person.surname}. All this is done outside any property placeholder resolvers.

This will obviously only work for property sources registered with the Environment.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • In my case, I was able to `@Autowire` in a `ConfigurableEnvironment` and skip retrieving the context. Everything is the same. – B. Anderson Feb 21 '18 at 16:31
-1

you might know this, but i'm just clarifying ${} is used to retrieve a property from properties file in to an XML file/ any other file where valid.

If you are trying to set personExpression= "person.surname" and want to retrieve it as you are doing it above (environment.getProperty("personExpression");) you should define like this personExpression= person.surname in your properties file. then it will work with environment.getProperty("personExpression"); and returns person.surname in your function, hope this helps

NagaRajendra
  • 159
  • 3
  • 16