7. Router

7.1 Router Implementations

Since content-based routing often requires some domain-specific logic, most use-cases will require Spring Integration's options for delegating to POJOs using the XML namespace support and/or Annotations. Both of these are discussed below, but first we present a couple implementations that are available out-of-the-box since they fulfill generic, but common, requirements.

7.1.1 PayloadTypeRouter

A PayloadTypeRouter will send Messages to the channel as defined by payload-type mappings.

<bean id="payloadTypeRouter" class="org.springframework.integration.router.PayloadTypeRouter">
    <property name="payloadTypeChannelMap">
        <map>
            <entry key="java.lang.String" value-ref="stringChannel"/>
            <entry key="java.lang.Integer" value-ref="integerChannel"/>
        </map>
    </property>
</bean>

Configuration of PayloadTypeRouter is also supported via the namespace provided by Spring Integration (see Section B.2, “Namespace Support”), which essentially simplifies configuration by combining <router/> configuration and its corresponding implementation defined using <bean/> element into a single and more concise configuration element. The example below demonstrates PayloadTypeRouter configuration which is equivalent to the one above using Spring Integration's namespace support:

<payload-type-router input-channel="routingChannel">
	<mapping type="java.lang.String" channel="stringChannel" />
	<mapping type="java.lang.Integer" channel="integerChannel" />
</payload-type-router>

7.1.2 HeaderValueRouter

A HeaderValueRouter will send Messages to the channel based on the individual header value mappings. When HeaderValueRouter is created it is initialized with the name of the header to be evaluated, using constructor-arg. The value of the header could be one of two things:

1. Arbitrary value

2. Channel name

If arbitrary value, then a channelResolver should be provided to map header values to channel names. The example below uses MapBasedChannelResolver to set up a map of header values to channel names.

 <bean id="myHeaderValueRouter"
		class="org.springframework.integration.router.HeaderValueRouter">
  <constructor-arg value="someHeaderName" /> 
  <property name="channelResolver">
    <bean class="org.springframework.integration.channel.MapBasedChannelResolver">
      <property name="channelMap">
        <map>
          <entry key="someHeaderValue" value-ref="channelA" />
          <entry key="someOtherHeaderValue" value-ref="channelB" />
        </map>
      </property>
    </bean>
  </property>
</bean>

If channelResolver is not specified, then the header value will be treated as a channel name making configuration much simpler, where no channelResolver needs to be specified.

 
<bean id="myHeaderValueRouter"
	class="org.springframework.integration.router.HeaderValueRouter">
	<constructor-arg value="someHeaderName" /> 
</bean>

Similar to the PayloadTypeRouter, configuration of HeaderValueRouter is also supported via namespace support provided by Spring Integration (see Section B.2, “Namespace Support”). The example below demonstrates two types of namespace-based configuration of HeaderValueRouter which are equivalent to the ones above using Spring Integration namespace support:

1. Configuration where mapping of header values to channels is required

<header-value-router input-channel="routingChannel" header-name="testHeader">
	<mapping value="someHeaderValue" channel="channelA" />
	<mapping value="someOtherHeaderValue" channel="channelB" />
</header-value-router>

2. Configuration where mapping of header values is not required if header values themselves represent the channel names

<header-value-router input-channel="routingChannel" header-name="testHeader"/>

[Note]Note
The two router implementations shown above share some common properties, such as "defaultOutputChannel" and "resolutionRequired". If "resolutionRequired" is set to "true", and the router is unable to determine a target channel (e.g. there is no matching payload for a PayloadTypeRouter and no "defaultOutputChannel" has been specified), then an Exception will be thrown.

7.1.3 RecipientListRouter

A RecipientListRouter will send each received Message to a statically-defined list of Message Channels:

<bean id="recipientListRouter" class="org.springframework.integration.router.RecipientListRouter">
    <property name="channels">
        <list>
            <ref bean="channel1"/>
            <ref bean="channel2"/>
            <ref bean="channel3"/>
        </list>
    </property>
</bean>

Configuration for RecipientListRouter is also supported via namespace support provided by Spring Integration (see Section B.2, “Namespace Support”). The example below demonstrates namespace-based configuration of RecipientListRouter and all the supported attributes using Spring Integration namespace support:

<recipient-list-router id="customRouter" input-channel="routingChannel"
				timeout="1234"
				ignore-send-failures="true"
				apply-sequence="true">
	<recipient channel="channel1"/>
	<recipient channel="channel2"/>
</recipient-list-router>

[Note]Note
The 'apply-sequence' flag here has the same affect as it does for a publish-subscribe-channel, and like publish-subscribe-channel it is disabled by default on the recipient-list-router. Refer to Section 3.5.3, “PublishSubscribeChannel Configuration” for more information.

7.2 The <router> element

The "router" element provides a simple way to connect a router to an input channel, and also accepts the optional default output channel. The "ref" may provide the bean name of a custom Router implementation (extending AbstractMessageRouter):

<router ref="payloadTypeRouter" input-channel="input1" default-output-channel="defaultOutput1"/>

<router ref="recipientListRouter" input-channel="input2" default-output-channel="defaultOutput2"/>

<router ref="customRouter" input-channel="input3" default-output-channel="defaultOutput3"/>

<beans:bean id="customRouterBean class="org.foo.MyCustomRouter"/>

Alternatively, the "ref" may point to a simple Object that contains the @Router annotation (see below), or the "ref" may be combined with an explicit "method" name. When specifying a "method", the same behavior applies as described in the @Router annotation section below.

<router input-channel="input" ref="somePojo" method="someMethod"/>

Using a "ref" attribute is generally recommended if the custom router implementation can be reused in other <router> definitions. However if the custom router implementation should be scoped to a concrete definition of the <router>, you can provide an inner bean definition:

<router method="someMethod" input-channel="input3" default-output-channel="defaultOutput3">
	<beans:bean class="org.foo.MyCustomRouter"/>
</router>

[Note]Note

Using both the "ref" attribute and an inner handler definition in the same <router> configuration is not allowed, as it creates an ambiguous condition and will result in an Exception being thrown.

7.3 The @Router Annotation

When using the @Router annotation, the annotated method can return either the MessageChannel or String type. In the case of the latter, the endpoint will resolve the channel name as it does for the default output. Additionally, the method can return either a single value or a collection. When a collection is returned, the reply message will be sent to multiple channels. To summarize, the following method signatures are all valid.

@Router
public MessageChannel route(Message message) {...}

@Router
public List<MessageChannel> route(Message message) {...}

@Router
public String route(Foo payload) {...}

@Router
public List<String> route(Foo payload) {...}

In addition to payload-based routing, a common requirement is to route based on metadata available within the message header as either a property or attribute. Rather than requiring use of the Message type as the method parameter, the @Router annotation may also use the @Header parameter annotation that is documented in Section B.5, “Annotation Support”.

@Router
public List<String> route(@Header("orderStatus") OrderStatus status)

[Note]Note
For routing of XML-based Messages, including XPath support, see Chapter 29, Dealing with XML Payloads.