Get property programmatically and evaluate it with SPEL

3.3k Views Asked by At

I am trying to mimic the @Value annotation programmatically by retrieving a property from the properties file using Environment and then evaluate the expression using SpelExpressionParser.

Here is a code snippet:

@Service
@Slf4j
public class Test {
    private String dynamicSPELStr = "#{${test.spel.map}.default}";

    @Autowired
    private Environment environment;
    void testSPEL() {
        ExpressionParser parser = new SpelExpressionParser();
        log.info("[PARSER] {}", parser
                .parseExpression(environment.resolvePlaceholders(dynamicSPELStr))
                .getValue());
    }
}

and the property is: test.spel.map={default: '5', key1: '10', key2: '20', key3: '40'}

However I am receiving the following error:

Expression [#{{default: '5', key1: '10', key2: '20', key3: '40'}.default}] @1: EL1043E: Unexpected token. Expected 'identifier' but was 'lcurly({)'

Running the same expression using @Value works just fine.

1

There are 1 best solutions below

2
On BEST ANSWER

The value attribute of a @Value annotation is not a SpEL expression. It supports placeholders using ${...}, and it supports SpEL expressions using #{...}.

It is only the text between #{ and } that is a SpEL expression. As such, remove the #{ and } from the dynamicSPELStr string:

private String dynamicSPELStr = "${test.spel.map}.default";

Explanation of error

SpEL expressions use #variableName to access a variable (see SpEL documentation, section 4.3.10. Variables).

Since the beginning of dynamicSPELStr is #{, the expression parser is complaining that the # variable prefix isn't followed by a valid name-character, hence the error "Expected 'identifier' but was 'lcurly({)'"