Moved the location of the documentation up a level
This commit is contained in:
359
spring-integration-reference/src/configuration.xml
Normal file
359
spring-integration-reference/src/configuration.xml
Normal file
@@ -0,0 +1,359 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter id="config">
|
||||
<title>Configuration</title>
|
||||
|
||||
<section id="config-intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
Spring Integration offers a number of configuration options. Which option you choose depends upon your particular
|
||||
needs and at what level you prefer to work. As with the Spring framework in general, it is also possible to mix
|
||||
and match the various techniques according to the particular problem at hand. For example, you may choose the
|
||||
XSD-based namespace for the majority of configuration combined with a handful of objects that are configured with
|
||||
annotations. Of course, it is also possible to always stick with a single approach. The main point is that these
|
||||
are <emphasis>options</emphasis> for configuration motivated by the need to support a user community with a wide
|
||||
range of preferences. That said, there has also been a concerted effort to provide consistent naming so that, for
|
||||
example, the XML elements defined by the XSD schema will match the names of annotations, and the attributes of
|
||||
those XML elements will match the names of annotation properties. Direct usage of the API is yet another option
|
||||
and is described in detail in <xref linkend="api"/>. We expect that most users will choose one of the
|
||||
higher-level options, such as the namespace-based or annotation-driven configuration.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="namespace">
|
||||
<title>Namespace Support</title>
|
||||
<para>
|
||||
Spring Integration components can be configured with XML elements that map directly to the terminology and
|
||||
concepts of enterprise integration. In many cases, the element names match those of the
|
||||
<ulink url="http://www.eaipatterns.com">Enterprise Integration Patterns</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
To enable Spring Integration's namespace support within your Spring configuration files, add the following
|
||||
namespace reference and schema mapping in your top-level 'beans' element:
|
||||
<programlisting><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
]]><emphasis>xmlns:integration="http://www.springframework.org/schema/integration"</emphasis><![CDATA[
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
]]><emphasis>http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd"</emphasis>></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
You can choose any name after "xmlns:"; <emphasis>integration</emphasis> is used here for clarity, but you might
|
||||
prefer a shorter abbreviation. Of course if you are using an XML-editor or IDE support, then the availability of
|
||||
auto-completion may convince you to keep the longer name for clarity. Alternatively, you can create configuration
|
||||
files that use the Spring Integration schema as the primary namespace:
|
||||
<programlisting><emphasis><beans:beans xmlns="http://www.springframework.org/schema/integration"</emphasis><![CDATA[
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
]]><emphasis>xmlns:beans="http://www.springframework.org/schema/beans"</emphasis><![CDATA[
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
When using this alternative, no prefix is necessary for the Spring Integration elements. On the other hand, if
|
||||
you want to define a generic Spring "bean" within the same configuration file, then a prefix would be required
|
||||
for the bean element (<beans:bean ... />). Since it is generally a good idea to modularize the
|
||||
configuration files themselves based on responsibility and/or architectural layer, you may find it appropriate to
|
||||
use the latter approach in the integration-focused configuration files, since generic beans are seldom necessary
|
||||
within those same files. For purposes of this documentation, we will assume the "integration" namespace is
|
||||
primary.
|
||||
</para>
|
||||
|
||||
<section id="namespace-channel">
|
||||
<title>Configuring Message Channels</title>
|
||||
<para>
|
||||
To create a Message Channel instance, use the 'channel' element:
|
||||
<programlisting><channel id="exampleChannel"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
You can also specify the channel's capacity: <programlisting><channel id="exampleChannel" capacity="100"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The default channel type is <emphasis>Point to Point</emphasis>. To create a
|
||||
<emphasis>Publish Subscribe</emphasis> channel, provide a value of <emphasis>true</emphasis> for the
|
||||
'publish-subscribe' attribute of the channel element:
|
||||
<programlisting><channel id="exampleChannel" publish-subscribe="true"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
When the <classname>MessageBus</classname> detects and registers channels, it will establish a dispatcher for
|
||||
each channel. The default dispatcher settings were previously displayed in
|
||||
<xref linkend="api-messagebus-dispatcherpolicy"/>. To customize these settings for a particular channel, add
|
||||
the 'dispatcher-policy' sub-element and provide one or more of the attributes shown below:
|
||||
<programlisting><![CDATA[<channel id="exampleChannel" publish-subscribe="true">
|
||||
<dispatcher-policy max-messages-per-task="25"
|
||||
receive-timeout="10"
|
||||
rejection-limit="3"
|
||||
retry-interval="500"
|
||||
should-fail-on-rejection-limit="false"/>
|
||||
</channel>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
To create a <ulink url="http://www.eaipatterns.com/DatatypeChannel.html">Datatype Channel</ulink> that only
|
||||
accepts messages containing a certain payload type, provide the fully-qualified class name in the
|
||||
channel element's <literal>datatype</literal> attribute:
|
||||
<programlisting><![CDATA[<channel id="numberChannel" datatype="java.lang.Number"/>]]></programlisting>
|
||||
Note that the type check passes for any type that is <emphasis>assignable</emphasis> to the channel's
|
||||
datatype. In other words, the "numberChannel" above would accept messages whose payload is
|
||||
<classname>java.lang.Integer</classname> or <classname>java.lang.Double</classname>. Multiple types can be
|
||||
provided as a comma-delimited list:
|
||||
<programlisting><![CDATA[<channel id="stringOrNumberChannel" datatype="java.lang.String,java.lang.Number"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Message channels may also have interceptors as described in <xref linkend="api-channelinterceptor"/>. One or
|
||||
more <interceptor> elements can be added as sub-elements of <channel>. Provide the "ref" attribute
|
||||
to reference any Spring-managed object that implements the <interfacename>ChannelInterceptor</interfacename>
|
||||
interface:
|
||||
<programlisting><![CDATA[<channel id="exampleChannel">
|
||||
]]><emphasis><![CDATA[<interceptor ref="trafficMonitoringInterceptor"/>]]></emphasis><![CDATA[
|
||||
</channel>]]></programlisting>
|
||||
In general, it is a good idea to define the interceptor implementations in a separate location since they
|
||||
usually provide common behavior that can be reused across multiple channels.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="namespace-endpoint">
|
||||
<title>Configuring Message Endpoints</title>
|
||||
<para>
|
||||
To create a Message Endpoint instance, use the 'endpoint' element with the 'input-channel' and 'handler-ref'
|
||||
attributes:
|
||||
<programlisting><endpoint input-channel="exampleChannel" handler-ref="exampleHandler"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The configuration above assumes that "exampleHandler" is an actual implementation of the
|
||||
<interfacename>MessageHandler</interfacename> interface as described in <xref linkend="api-messagehandler"/>.
|
||||
To delegate to an arbitrary method of any object, simply add the "handler-method" attribute.
|
||||
<programlisting><endpoint input-channel="exampleChannel" handler-ref="somePojo" handler-method="someMethod"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
In either case (<interfacename>MessageHandler</interfacename> or arbitrary object/method), when the handling
|
||||
method returns a non-null value, the endpoint will attempt to send the reply message to an appropriate reply
|
||||
channel. To determine the reply channel, it will first check for a value in the message header's
|
||||
'<literal>returnAddress</literal>' property. If that value is available, it will then check its type. If it is
|
||||
a <classname>MessageChannel</classname>, the reply message will be sent to that channel. If it is a
|
||||
<classname>String</classname>, then the endpoint will attempt to resolve the channel by performing a
|
||||
lookup in the <interfacename>ChannelRegistry</interfacename>. If the message header does not contain a
|
||||
'returnAddress' property at all, then it will fallback to its own 'defaultOutputChannelName' property. If
|
||||
neither is available, then a <classname>MessageHandlingException</classname> will be thrown. To configure the
|
||||
default output channel when using the XML namespace, provide the 'default-output-channel' attribute:
|
||||
<programlisting><endpoint input-channel="exampleChannel"
|
||||
handler-ref="somePojo"
|
||||
handler-method="someMethod"
|
||||
default-output-channel="replyChannel"/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Endpoint's also support <interfacename>MessageSelectors</interfacename> as described in
|
||||
<xref linkend="api-messageselector"/>. To configure selectors with namespace support, simply add one or more
|
||||
<selector> sub-elements to the endpoint definition:
|
||||
<programlisting><![CDATA[<endpoint id="endpoint" input-channel="channel" handler-ref="handler">
|
||||
]]><emphasis><![CDATA[<selector ref="exampleSelector"/>]]></emphasis><![CDATA[
|
||||
</endpoint>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
When the <interfacename>MessageBus</interfacename> registers the endpoint, it will activate the subscription
|
||||
by assigning the endpoint to the input channel's dispatcher. The dispatcher is capable of handling multiple
|
||||
endpoint subscriptions for its channel and delegates to a scheduler for managing the tasks that pull messages
|
||||
from the channel and push them to the endpoints. To configure the polling period for an individual endpoint's
|
||||
schedule, provide a 'schedule' sub-element with the 'period' in milliseconds:
|
||||
<programlisting><![CDATA[<endpoint input-channel="exampleChannel" handler-ref="exampleHandler"/>
|
||||
]]><emphasis><![CDATA[<schedule period="3000"/>]]></emphasis><![CDATA[
|
||||
</endpoint>]]></programlisting>
|
||||
</para>
|
||||
<note>
|
||||
Individual endpoint schedules only apply for "Point-to-Point" channels, since in that case only a single
|
||||
subscriber needs to receive the message. On the other hand, when a Spring Integration channel is configured as
|
||||
a "Publish-Subscribe" channel, then the dispatcher will drive all endpoint notifications according to its own
|
||||
default schedule, and any 'schedule' element configured for those endpoints will be ignored.
|
||||
</note>
|
||||
<para>
|
||||
One of the most important configuration options for endpoints is the concurrency policy. Each endpoint is
|
||||
capable of managing a thread pool for its handler, and the values you provide for that pool's core and max
|
||||
size can make a substantial difference in how the handler performs under load. These settings are available
|
||||
per-endpoint since the performance characteristics of an endpoint's handler is one of the major factors to
|
||||
consider (the other major factor being the expected volume on the channel to which the endpoint subscribes).
|
||||
To enable concurrency for an endpoint that is configured with the XML namespace support, provide the
|
||||
'concurrency' sub-element and one or more of the properties shown below:
|
||||
<programlisting><![CDATA[<endpoint input-channel="exampleChannel" handler-ref="exampleHandler"/>
|
||||
]]><emphasis><![CDATA[<concurrency core="5" max="25" queue-capacity="20" keep-alive="120"/>]]></emphasis><![CDATA[
|
||||
</endpoint>]]></programlisting>
|
||||
Recall the default concurrency policy values as listed in <xref linkend="api-messagebus-concurrencypolicy"/>.
|
||||
</para>
|
||||
<tip>
|
||||
The default queue capacity of 0 triggers the creation of a <classname>SynchronousQueue</classname>. In many
|
||||
cases, this is preferable since the direct handoff eliminates the chance of a message handling task being
|
||||
"stuck" in the queue (thread pool executors will favor adding to the queue rather than increasing the pool
|
||||
size). Specifically, whenever a dispatcher for a Point-to-Point channel has more than one subscribed endpoint,
|
||||
a task that is rejected due to an exhausted thread pool can be handled immediately by another endpoint whose
|
||||
pool has one or more threads available. On the other hand, when a particular channel/endpoint may be expecting
|
||||
bursts of activity, setting a queue capacity value might be the best way to accommodate the volume.
|
||||
</tip>
|
||||
</section>
|
||||
|
||||
<section id="namespace-messagebus">
|
||||
<title>Configuring the Message Bus</title>
|
||||
<para>
|
||||
As described in <xref linkend="api-messagebus"/>, the <classname>MessageBus</classname> plays a central role.
|
||||
Nevertheless, its configuration is quite simple since it is primarily concerned with managing internal details
|
||||
based on the configuration of channels and endpoints. The bus is aware of its host application context, and
|
||||
therefore is also capable of auto-detecting the channels and endpoints. Typically, the
|
||||
<classname>MessageBus</classname> can be configured with a single empty element:
|
||||
<programlisting><message-bus/></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The Message Bus provides default error handling for its components in the form of a configurable error channel,
|
||||
and the 'message-bus' element accepts a reference with its 'error-channel' attribute:
|
||||
<programlisting><![CDATA[<message-bus error-channel="errorChannel"/>
|
||||
|
||||
<channel id="errorChannel" publish-subscribe="true" capacity="500"/>]]></programlisting>
|
||||
When exceptions occur in an endpoint's execution of its <interfacename>MessageHandler</interfacename> callback,
|
||||
those exceptions will be wrapped in <classname>ErrorMessages</classname> and sent to the Message Bus'
|
||||
'errorChannel' by default. To enable global error handling, simply register a handler on that channel. For
|
||||
example, you can configure Spring Integration's <classname>PayloadTypeRouter</classname> as the handler of
|
||||
an endpoint that is subscribed to the 'errorChannel'. That router can then spread the error messages across
|
||||
multiple channels based on <classname>Exception</classname> type.
|
||||
</para>
|
||||
<para>
|
||||
The 'message-bus' element accepts two more optional attributes. First is the size of the dispatcher thread
|
||||
pool. The dispatcher threads are responsible for polling channels and then passing the messages to handlers.
|
||||
When the endpoints are concurrency-enabled as described in the previous section, the invocation of the handling
|
||||
methods will happen within the handler thread pool and not the dispatcher pool. Finally, the Message Bus is
|
||||
capable of automatically creating channel instances (with default settings) if an endpoint registers a
|
||||
subscription by providing the name of a channel that the bus does not recognize.
|
||||
<programlisting><![CDATA[<message-bus dispatcher-pool-size="25" auto-create-channels="true"/>]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="namespace-adapters">
|
||||
<title>Configuring Channel Adapters</title>
|
||||
<para>
|
||||
The most convenient way to configure Channel Adapters is by using the namespace support. The following examples
|
||||
demonstrate the namespace-based configuration of source and target adapters (Spring Integration 1.0 M1 includes
|
||||
namespace support for JMS and Files):
|
||||
<programlisting><![CDATA[
|
||||
<jms-source connection-factory="connectionFactory" destination="inputQueue" channel="inputChannel1"/
|
||||
|
||||
<jms-target connection-factory="connectionFactory" destination="outputQueue" channel="outputChannel1"/>
|
||||
|
||||
<file-source directory="/tmp/input" channel="inputChannel2" poll-period="10000"/>
|
||||
|
||||
<file-target directory="/tmp/output" channel="outputChannel2"/>
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="namespace-annotationdriven">
|
||||
<title>Enabling Annotation-Driven Configuration</title>
|
||||
<para>
|
||||
The next section will describe Spring Integration's support for annotation-driven configuration. To enable
|
||||
those features, add this single element to the XML-based configuration:
|
||||
<programlisting><annotation-driven/></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="annotations">
|
||||
<title>Annotations</title>
|
||||
<para>
|
||||
In addition to the XML namespace support for configuring Message Endpoints, it is also possible to use
|
||||
annotations. The class-level <interfacename>@MessageEndpoint</interfacename> annotation indicates that the
|
||||
annotated class is capable of being registered as an endpoint, and the method-level
|
||||
<interfacename>@Handler</interfacename> annotation indicates that the annotated method is capable of handling
|
||||
a message.
|
||||
<programlisting>@MessageEndpoint(input="fooChannel")
|
||||
public class FooService {
|
||||
|
||||
@Handler
|
||||
public void processMessage(Message message) {
|
||||
...
|
||||
}
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
In most cases, the annotated handler method should not require the <classname>Message</classname> type as its
|
||||
parameter. Instead, the method parameter type can match the message's payload type.
|
||||
<programlisting>@MessageEndpoint(input="fooChannel")
|
||||
public class FooService {
|
||||
|
||||
@Handler
|
||||
public void processFoo(<emphasis>Foo foo</emphasis>) {
|
||||
...
|
||||
}
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
As described in the previous section, when the handler method returns a non-null value, the endpoint will
|
||||
attempt to send a reply. This is consistent across both configuration options (namespace and annotations) in that
|
||||
the message header's 'replyChannelName' property will be used if available, and the endpoint's default output is
|
||||
the fallback. To configure the default output for an annotation-driven endpoint, provide the 'defaultOutput'
|
||||
attribute on the <interfacename>@MessageEndpoint</interfacename>.
|
||||
<programlisting>@MessageEndpoint(input="exampleChannel", defaultOutput="replyChannel")</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Finally, just as the 'schedule' sub-element and its 'period' attribute can be provided for a namespace-based
|
||||
endpoint, the 'pollPeriod' attribute can be provided on the <interfacename>@MessageEndpoint</interfacename>.
|
||||
<programlisting>@MessageEndpoint(input="exampleChannel", pollPeriod=3000)</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Two additional annotations are supported, and both act as a special form of handler method:
|
||||
<interfacename>@Router</interfacename> and <interfacename>@Splitter</interfacename>. As with the
|
||||
<interfacename>@Handler</interfacename> annotation, methods annotated with either of these two annotations can
|
||||
either accept the <classname>Message</classname> itself or the message payload type as the parameter.
|
||||
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>@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) {...}</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 map to either a property or attribute name.
|
||||
<programlisting>@Router(property="customerType")
|
||||
public String route(String customerType)
|
||||
|
||||
@Router(attribute="orderStatus")
|
||||
public List<String> route(OrderStatus status)</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The <interfacename>@Splitter</interfacename> annotation is also applicable to methods that expect either the
|
||||
<interfacename>Message</interfacename> type or the message payload type, and the return values of the method
|
||||
should be a collection of any type. If the returned values are not actual <interfacename>Message</interfacename>
|
||||
objects, then each of them will be sent as the payload of a message. The <interfacename>@Splitter</interfacename>
|
||||
annotation expects a 'channel' attribute that specifies the channel name to which those messages should be sent.
|
||||
<programlisting>@Splitter(channel="exampleChannel")
|
||||
List<LineItem> extractItems(Order order) {
|
||||
return order.getItems()
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
The <interfacename>@Publisher</interfacename> annotation is a convenience for sending messages with AOP
|
||||
<emphasis>after-returning advice</emphasis>. For example, each time the following method is invoked, its return
|
||||
value will be sent to the "fooChannel":
|
||||
<programlisting><![CDATA[@Publisher(channel="fooChannel")
|
||||
public String foo() {
|
||||
return "bar";
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Similarly, the <interfacename>@Subscriber</interfacename> annotation triggers the retrieval of messages from a
|
||||
channel, and the payload of each message will then be sent as input to an arbitrary method. This is one of the
|
||||
simplest ways to configure asynchronous, event-driven behavior:
|
||||
<programlisting><![CDATA[@Subscriber(channel="fooChannel")
|
||||
public void log(String foo) {
|
||||
System.out.println(foo);
|
||||
}]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user