chimiz13
chimiz13

Reputation: 85

Spring Integration DSL Filter vs. RouteToRecipients w/ single Recipient and DefaultOutputToParentFlow

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

Answers (1)

Artem Bilan
Artem Bilan

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

Related Questions