Description
In what version(s) of Spring Integration are you seeing this issue?
5.1.4.RELEASE
Describe the bug
When creating an IntegrationFlow bean using IntegrationFlows.from(CHANNEL)
, in the route(Function<S, T> router, Consumer<RouterSpec<T, MethodInvokingRouter>> routerConfigurer)
method, when configuring the router mappings, the method defaultOutputToParentFlow()
does not what the documentation says it does.
Example:
Given this Integration Flow definition:
@Bean
public IntegrationFlow orderIntegrationFlow() {
return IntegrationFlows.from(CHANNEL)
.<Order, OrderType>route(Order::getType,
r -> r.channelMapping(OrderType.DINE_IN, DineInOrderFlow.CHANNEL)
.channelMapping(OrderType.ONLINE, OnlineOrderFlow.CHANNEL)
.defaultOutputToParentFlow()
)
.log("It only reaches here if Order::getType is null.")
.get();
}
The log will only get printed if Order::getType
is null. This is contrary to the javadoc which says that:
Make a default output mapping of the router to the parent flow. Use the next, after router, parent flow MessageChannel as a AbstractMessageRouter.setDefaultOutputChannel(MessageChannel) of this router.
To Reproduce
Create a Spring project in Java 11, using Spring 5.3.20 and Spring Integration 5.1.4.RELEASE .
Create an IntegrationFlow bean using the default IntegrationFlows.from()
method:
public static final String CHANNEL = "orderInputChannel";
@Bean(name = CHANNEL)
public MessageChannel getChannel() {
DirectChannel dc = new DirectChannel();
dc.setComponentName(CHANNEL);
return dc;
}
@Bean
public IntegrationFlow orderIntegrationFlow() {
return IntegrationFlows.from(CHANNEL)
.<Order, OrderType>route(Order::getType,
r -> r.channelMapping(OrderType.DINE_IN, DineInOrderFlow.CHANNEL)
.channelMapping(OrderType.ONLINE, OnlineOrderFlow.CHANNEL)
.defaultOutputToParentFlow()
)
.log("It only reaches here if Order::getType is null.")
.get();
}
Create a class called Order:
public class Order {
private OrderType orderType;
public OrderType getType() {
return orderType;
}
public void setType(OrderType orderType) {
this.orderType = orderType;
}
}
And an enum called OrderType:
public enum OrderType {
DINE_IN,
ONLINE,
TAKEAWAY;
}
And with everything setup correctly, send a message to CHANNEL of an Order
with OrderType.TAKEAWAY
.
Expected behavior
The log()
at the end of the orderIntegrationFlow
will be called because the defaultOutputToParent
reached a default state.
** Actual behavior **
An Exception is thrown where TAKEAWAY is not found to be a proper CHANNEL name defined in the Spring Context. Only if Order::getOrderType returns null, then the log()
function is called.
Sample
A link to a GitHub repository with a minimal, reproducible sample.
Reports that include a sample will take priority over reports that do not.
At times, we may require a sample, so it is good to try and include a sample up front.