javaspringspring-integrationspelevaluationexception

Output channel routing


I am trying to rewrite Spring Integration flow from XML to Java. I would like to route data sent over a channel:

@Bean(name = "sendData")
public MessageChannel getSendData() {
    return MessageChannels.direct()
                          .get();
}

into two other channels:

@Bean(name = "sendDataA")
public MessageChannel getSendDataA() {
    return MessageChannels.direct()
                          .get();
}

@Bean(name = "sendDataB")
public MessageChannel getSendDataB() {
    return MessageChannels.direct()
                          .get();
}

depending on their availability.

I have a RoundRobinRouter class that determines which output channel to use. It has a method route that returns output channel name, like:

@Component
class RoundRobinRouter {
    public String route(Object payload) {
        /* implementation */
    }
}

Note that route method implementation does not actually use the payload object. It was previously placed in XML configuration:

<int:router method="route" input-channel="sendData"
            default-output-channel="sendDataA">
    <bean
            class="com.example.RoundRobinRouter"/>
</int:router>

I have already tried using Java DSL IntegrationFlow:

@Bean
@ServiceActivator(inputChannel = "sendData",
                  outputChannel = "sendDataA")
public IntegrationFlow routeRoundRobin() {
    return router -> router.route(roundRobinRouter, "route");
}

But I was getting an error "Dispatcher has no subscribers" on sendData.send(payload) call, apparently caused by:

org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 8): Method call: Method configure(com.example.DataType) cannot be found on com.example.Integration$$Lambda$1/1018103616 type

The router is the only lambda in my Integration class.


Solution

  • Okay, I got it to work. I'm not sure which change fixed my problem, but here's correct router implementation:

    @Bean
    public IntegrationFlow routeRoundRobin() {
        return IntegrationFlows.from(getSendData())
                               .route(roundRobinRouter, "route",
                                      r -> r.channelMapping("sendDataA",
                                                            "sendDataA")
                                            .channelMapping("sendDataB",
                                                            "sendDataB"))
                               .get();
    }
    
    @Bean(name = "sendData")
    public MessageChannel getSendData() {
        return MessageChannels.direct()
                              .get();
    }
    
    @Bean(name = "sendDataA")
    public MessageChannel getSendDataA() {
        return MessageChannels.direct()
                              .get();
    }
    
    @Bean(name = "sendDataB")
    public MessageChannel getSendDataB() {
        return MessageChannels.direct()
                              .get();
    }
    

    I changed @ServiceActivator to IntegrationFlow from sendData, and also added channel mapping to the router.