Search code examples
spring-integrationspring-el

Spring Integration - Use SpEL in service-activator nested bean constructor-arg


I am trying to use a factory-method to initialize a service-activator as below

<int:service-activator>
    <bean class="com.sample.FileWriterFactory" factory-method="createFileWriter">
        <constructor-arg index="0" value="${xml.out-directory}/xml"/>
        <constructor-arg index="1" value="#{ headers['file_name'] + '.xml' }"/>
    </bean>
</int:service-activator>

However, the SpEL evaluation fails since the headers property is not found in the evaluation context. The exact error snippet is

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'headers' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?

The purpose of doing this is that I want to reuse the same POJO by passing different parameters as needed. What am I doing wrong?


Solution

  • #{...} expressions are evaluated once, during context initialization.

    Expressions accessing properties (such as headers) like that need to be evaluated at runtime (against the message as the root object).

    If that's what you are trying to do, use value="headers['file_name'] + '.xml'" and then, within your constructor...

    private final Expression expression;
    
    public FileWriterFactory(String directory, String expression) {
        ...
        this.expression = new SpelExpressionParser().parseExpression(expression);
    }
    

    then, in your runtime service method

    String fileName = this.expression.getValue(message, String.class);