Files
spring-integration/spring-integration-reference/src/router.xml
Mark Fisher b416eca31e INT-676
2009-07-04 01:36:47 +00:00

205 lines
11 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="router">
<title>Router</title>
<section id="router-implementations">
<title>Router Implementations</title>
<para>
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.
</para>
<section id="router-implementations-payloadtyperouter">
<title>PayloadTypeRouter</title>
<para>
A <classname>PayloadTypeRouter</classname> will send Messages to the channel as defined by payload-type
mappings.
<programlisting language="xml"><![CDATA[<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>]]></programlisting>
</para>
<para>
Configuration of <classname>PayloadTypeRouter</classname> is also supported via the namespace provided by Spring Integration (see <xref linkend="configuration-namespace"/>),
which essentially simplifies configuration by combining <code>&lt;router/&gt;</code> configuration and its corresponding implementation defined using <code>&lt;bean/&gt;</code> element
into a single and more concise configuration element.
The example below demonstrates <classname>PayloadTypeRouter</classname> configuration which is equivalent to the one above using Spring Integration's namespace support:
</para>
<para>
<programlisting language="xml"><![CDATA[<payload-type-router input-channel="routingChannel">
<mapping type="java.lang.String" channel="stringChannel" />
<mapping type="java.lang.Integer" channel="integerChannel" />
</payload-type-router>]]></programlisting>
</para>
</section>
<section id="router-implementations-headervaluerouter">
<title>HeaderValueRouter</title>
<para>
A <classname>HeaderValueRouter</classname> will send Messages to the channel based on the individual header value mappings.
When <code>HeaderValueRouter</code> is created it is initialized with the <emphasis>name</emphasis> of the header to be evaluated, using <code>constructor-arg</code>.
The <emphasis>value</emphasis> of the header could be one of two things:</para>
<para>
1. Arbitrary value
</para>
<para>
2. Channel name
</para>
<para>
If arbitrary value, then a <code>channelResolver</code> should be provided to map <emphasis>header values</emphasis> to <emphasis>channel names</emphasis>.
The example below uses <code>MapBasedChannelResolver</code> to set up a map of header values to channel names.
<programlisting language="xml"><![CDATA[ <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>
]]></programlisting>
If <code>channelResolver</code> is not specified, then the <emphasis>header value</emphasis> will be treated as a <emphasis>channel name</emphasis>
making configuration much simpler, where no <code>channelResolver</code> needs to be specified.
<programlisting language="xml"><![CDATA[
<bean id="myHeaderValueRouter"
class="org.springframework.integration.router.HeaderValueRouter">
<constructor-arg value="someHeaderName" />
</bean>
]]></programlisting>
</para>
<para>
Similar to the <classname>PayloadTypeRouter</classname>, configuration of <classname>HeaderValueRouter</classname> is also supported via namespace support provided by Spring Integration (see <xref linkend="configuration-namespace"/>).
The example below demonstrates two types of namespace-based configuration of <classname>HeaderValueRouter</classname> which are equivalent to the ones above using Spring Integration namespace support:
</para>
<para>1. Configuration where mapping of header values to channels is required</para>
<para>
<programlisting language="xml"><![CDATA[<header-value-router input-channel="routingChannel" header-name="testHeader">
<mapping value="someHeaderValue" channel="channelA" />
<mapping value="someOtherHeaderValue" channel="channelB" />
</header-value-router>]]></programlisting>
</para>
<para>2. Configuration where mapping of header values is not required if header values themselves represent the channel names</para>
<para>
<programlisting language="xml"><![CDATA[<header-value-router input-channel="routingChannel" header-name="testHeader"/>]]></programlisting>
</para>
<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.
</note>
</section>
<section id="router-implementations-recipientlistrouter">
<title>RecipientListRouter</title>
<para>
A <classname>RecipientListRouter</classname> will send each received Message to a statically-defined
list of Message Channels:
<programlisting language="xml"><![CDATA[<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>]]></programlisting>
</para>
</section>
<para>
Configuration for <classname>RecipientListRouter</classname> is also supported via namespace support provided by Spring Integration (see <xref linkend="configuration-namespace"/>).
The example below demonstrates namespace-based configuration of <classname>RecipientListRouter</classname> and all the supported attributes using Spring Integration namespace support:
</para>
<para>
<programlisting language="xml"><![CDATA[<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>]]></programlisting>
</para>
<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
<xref linkend="channel-configuration-pubsubchannel"/> for more information.
</note>
</section>
<section id="router-namespace">
<title>The &lt;router&gt; element</title>
<para>
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):
<programlisting language="xml"><![CDATA[<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"/>]]></programlisting>
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.
<programlisting language="xml"><![CDATA[<router input-channel="input" ref="somePojo" method="someMethod"/>]]></programlisting>
Using a "ref" attribute is generally recommended if the custom router implementation can be reused in other
<code>&lt;router&gt;</code> definitions. However if the custom router implementation should be scoped to a
concrete definition of the <code>&lt;router&gt;</code>, you can provide an inner bean definition:
<programlisting language="xml"><![CDATA[<router method="someMethod" input-channel="input3" default-output-channel="defaultOutput3">
<beans:bean class="org.foo.MyCustomRouter"/>
</router>]]></programlisting>
</para>
<note>
<para>
Using both the "ref" attribute and an inner handler definition in the same <code>&lt;router&gt;</code> configuration
is not allowed, as it creates an ambiguous condition and will result in an Exception being thrown.
</para>
</note>
</section>
<section id="router-annotation">
<title>The @Router Annotation</title>
<para>
When using the <interfacename>@Router</interfacename> annotation, the annotated method can return either the
<interfacename>MessageChannel</interfacename> or <classname>String</classname> 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.
<programlisting language="java">@Router
public MessageChannel route(Message message) {...}
@Router
public List&lt;MessageChannel&gt; route(Message message) {...}
@Router
public String route(Foo payload) {...}
@Router
public List&lt;String&gt; route(Foo payload) {...}</programlisting>
</para>
<para>
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
<interfacename>Message</interfacename> type as the method parameter, the <interfacename>@Router</interfacename>
annotation may also use the @Header parameter annotation that is documented in <xref linkend="annotations"/>.
<programlisting language="java">@Router
public List&lt;String&gt; route(@Header("orderStatus") OrderStatus status)</programlisting>
</para>
</section>
<note>
For routing of XML-based Messages, including XPath support, see <xref linkend="xml"/>.
</note>
</chapter>