Search code examples
spring-integrationspring-integration-dsl

How to parse and get headers property values externally in Spring Integration


I need to parse and get headers property value which I send via MessagingGateway, I doubt if it has something to do with IntegrationEvaluationContext

Here is what I tried and failed miserably:

@Bean
public IntegrationFlow deleteFiles(){
    return IntegrationFlows.from("integration.channel.bulk-delete")
            .handle(Sftp.outboundGateway(sftpSessionFactory(),
            AbstractRemoteFileOutboundGateway.Command.LS,"headers[path]")
                    .options(AbstractRemoteFileOutboundGateway.Option.NAME_ONLY)
                    .filterFunction(file->{
                     //Here I'm trying to get the age value from headers
                        int age = ExpressionUtils.intExpression("headers[age]").getValue(integrationEvaluationContext.getObject(),Integer.class);
                        Instant decidedTime = Instant.now().minus(age, ChronoUnit.SECONDS);
                        return Instant.ofEpochSecond(file.getAttrs().getMTime()).isBefore(decidedTime);
                    }))
                   .get();

The error message:

org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'headers' cannot be found on null 

I even tried autowiring StandardEvaluationContext and passing:

new SpelExpressionParser().parseExpression("headers[age]").getValue(standardEvaluationContext)

How can I get the EvaluationContext and pass it so that headers[] get parsed?


Solution

  • The filters don't have access to the gateway's input message; they only have access to the LsEntry.

    You need to provide the age some other way, perhaps store it in a ThreadLocal.

    public class AgeHolder {
    
         private static final ages = new ThreadLocal<Integer>;
    
         public static setAge(int age) {
             ages.set(age);
         }
    
         public static Integer getAge() {
             Integer age = ages.get();
             ages.remove();
             return age;
         }
    
    }
    

    Then T(AgeHolder).getAge() in the expression.

    Or you can do the filtering in Spring Integration instead

    
        .from(Sfp...) // not NAME_ONLY
        .split
        .filter(...) // use the `headers` and `payload`
        .transform(...) -> LsEntry -> name
        .aggregate()
        ...