Reputation: 85
I am needing to route a message from my parent flow into a new flow when a given evaluation returns false but have it continue in the parent flow when that evaluation returns true. Currently I have been able to successfully implement this functionality using the Spring Integration DSL .filter()
method without any issues. However, I feel as if though using .filter()
in this way does not fall under the true intention of this method. Is there a certain type of router that can be used to better achieve this same need? Is it necessary to change from this .filter()
implementation to a router based implementation?
Given the below Integration Flow configuration as an example...
@Bean
public IntegrationFlow flow() {
return IntegrationFlows
.from("inboundChannel")
.filter(someService::someTrueFalseMethod, onFalseReturn -> onFalseReturn.discardChannel("otherFlowInboundChannel"))
.handle(someService::someHandleMethod)
.get();
}
@Bean
public IntegrationFlow otherFlow() {
return IntegrationFlows
.from("otherFlowInboundChannel")
.handle(someOtherService::someOtherHandleMethod)
.get();
}
Up to this point it seems .routeToRecipents()
might be what I need to use. In my scenario, I need to evaluate the headers of the message so that is why the recipientMessageSelector
is being used.
@Bean
public IntegrationFlow flow() {
return IntegrationFlows
.from("inboundChannel"
.routeToRecipients(router -> router
.recipientMessageSelector("otherFlowInboundChannel", someService::someTrueFalseMethod)
.defaultOutputToParentFlow()
)
.handle(someService::someHandleMethod)
.get();
}
@Bean
public IntegrationFlow otherFlow() {
return IntegrationFlows
.from("otherFlowInboundChannel")
.handle(someOtherService::someOtherHandleMethod)
.get();
}
Even with this routeToRecipients
solution that appears to work, is there really any benefit gained between it and the filter implementation above?
Upvotes: 5
Views: 2467
Reputation: 121542
Well, it is really not about a Java DSL methods and how to use them. It is really about a theory around those IE patterns.
Let's compare Filter
and RecipientListRouter
from EIP!
Filter - https://www.enterpriseintegrationpatterns.com/patterns/messaging/Filter.html:
If the message content matches the criteria specified by the Message Filter, the message is routed to the output channel. If the message content does not match the criteria, the message is discarded.
So, technically filter
doesn't match your expectations since on false
resolution you kinda discard message. However for possible processing on those discarded messages Spring Integration provides a discardChannel
option to initiate a discard sub-flow. So, we can treat it as if..else
construction...
Recipient List - https://www.enterpriseintegrationpatterns.com/patterns/messaging/RecipientList.html
Then use a Recipient List to inspect an incoming message, determine the list of desired recipients, and forward the message to all channels associated with the recipients in the list.
So, kinda what you need, because you evaluate a message and recipients for it and then send to their channels. Only the problem with this that emulate a filter
behavior because you are not going to have a more than two channels with mutually exclusive purpose.
When the filter
approach feels like a flow control abusing (reminds me a similar logic in Java relied on the exception handling for flow control), it doesn't dictate us to stay with always canonical behavior to end up with an error when message doesn't fit a condition.
The recipientList
is for more complicated scenarios when a selector is used for any arbitrary evaluation, not just plain boolean and has an ability to distribute the same message into several output channels. So, I wouldn't recommend it for this simple true/false
scenario.
You may consider to look into another similar pattern:
Content Based Router - https://www.enterpriseintegrationpatterns.com/patterns/messaging/ContentBasedRouter.html
Use a Content-Based Router to route each message to the correct recipient based on message content.
This one feels like very close to what you need with true/false
and it is not going to abuse errors (discards) for flow cotrol and doesn't dictate us a list of recipients. And this one also has that defaultOutputToParentFlow()
when you would like to rely on non-mapped result.
IMHO, I would stay with filter()
- with its true/false
logic and discardChannel
it really looks like particular implementation of that Content Based Router :-).
Upvotes: 4