9

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?

otto.poellath
  • 4,129
  • 6
  • 45
  • 60

3 Answers3

10

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.

otto.poellath
  • 4,129
  • 6
  • 45
  • 60
  • 12
    If you're reading this for Spring Integration 2.1+, ignore-channel-name-resolution-failures has been dropped. You can get the same effect by useing resolution-required="false". See http://static.springsource.org/spring-integration/reference/htmlsingle/#2.1-router-standardization – Joe Jul 13 '12 at 18:45
1

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();
m190
  • 351
  • 5
  • 11
0

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>
Ramneek Handa
  • 53
  • 1
  • 10