otto.poellath
otto.poellath

Reputation: 4239

Spring Integration: Content based router with default output channel?

I'd like use Spring Integration to implement a content based router that uses a default output channel if the expression value doesn't match any of the mappings. Here's my bean definition:

<int:router input-channel="channel_in" default-output-channel="channel_default" expression="payload.name">
    <int:mapping value="foo" channel="channel_one" />
    <int:mapping value="bar" channel="channel_two" />

However, it seems the default output channel is never used. If the expression evaluates to e.g. 'baz', the router seems to be looking for a channel named 'baz', instead of routing to the 'channel_default' channel:

org.springframework.integration.MessagingException: failed to resolve channel name 'baz'
  Caused by: org.springframework.integration.support.channel.ChannelResolutionException: 
    failed to look up MessageChannel bean with name 'baz'
  Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
    No bean named 'baz' is defined

Is what I want at all possible using the XML namespace, or do I need to code up my own implementation?

Upvotes: 9

Views: 15591

Answers (3)

m190
m190

Reputation: 361

As mentioned in reference docs:

As of Spring Integration 2.1, router parameters have been more standardized across all router implementations. Consequently, a few minor changes may break older Spring Integration based applications.

Since Spring Integration 2.1, the ignore-channel-name-resolution-failures attribute is removed in favor of consolidating its behavior with the resolution-required attribute. Also, the resolution-required attribute now defaults to true.

Prior to these changes, the resolution-required attribute defaulted to false, causing messages to be silently dropped when no channel was resolved and no default-output-channel was set. The new behavior requires at least one resolved channel and, by default, throws a MessageDeliveryException if no channel was determined (or an attempt to send was not successful).

If you do desire to drop messages silently, you can set default-output-channel="nullChannel".

And if you are using Java DSL, the configuration may looks like this:

IntegrationFlows.from("process")
        .<JobExecution, String>route(m -> m.getExitStatus().getExitCode(),
                m -> m.channelMapping(ExitStatus.COMPLETED.getExitCode(), "succeed")
                        .defaultOutputChannel("failed")
                        .resolutionRequired(false))
        .get();

Upvotes: 1

Ramneek Handa
Ramneek Handa

Reputation: 63

if you are using for Spring boot 2.1.2.RELEASE

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>

then resolution-required="false" is required instead of ignore-channel-name-resolution-failures.

<int:router input-channel="channel_in" default-output-channel="channel_default" 
  expression="payload.name" resolution-required="false">
    <int:mapping value="foo" channel="channel_one" />
    <int:mapping value="bar" channel="channel_two" />
</int:router>

Upvotes: 0

otto.poellath
otto.poellath

Reputation: 4239

Turns out that all I had to to to make this work was to set the router's ignore-channel-name-resolution-failures attribute to false:

<int:router input-channel="channel_in" default-output-channel="channel_default" 
  expression="payload.name" ignore-channel-name-resolution-failures="true">
    <int:mapping value="foo" channel="channel_one" />
    <int:mapping value="bar" channel="channel_two" />
</int:router>

I thought I had tried that before, but I seems I didn't.

Upvotes: 10

Related Questions