Jezor Jezor - 1 month ago 20
Java Question

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.

Answer

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.