Skip to content

Spring DSL defaultOutputToParentFlow does not behave as described #3946

Closed
@dobretony

Description

@dobretony

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions