258 lines
17 KiB
XML
258 lines
17 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<appendix id="configuration">
|
|
<title>Configuration</title>
|
|
<section id="configuration-introduction">
|
|
<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. As much as possible, the two provide consistent naming. 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 of course always an option, but we expect that most users will choose one
|
|
of the higher-level options, or a combination of the namespace-based and annotation-driven configuration.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="configuration-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 core namespace support within your Spring configuration files, add the following
|
|
namespace reference and schema mapping in your top-level 'beans' element:
|
|
<programlisting language="xml"><![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 language="xml"><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>
|
|
<para>
|
|
Many other namespaces are provided within the Spring Integration distribution. In fact, each adapter type (JMS,
|
|
File, etc.) that provides namespace support defines its elements within a separate schema. In order to use these
|
|
elements, simply add the necessary namespaces with an "xmlns" entry and the corresponding "schemaLocation" mapping.
|
|
For example, the following root element shows several of these namespace declarations:
|
|
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:integration="http://www.springframework.org/schema/integration"
|
|
xmlns:file="http://www.springframework.org/schema/integration/file"
|
|
xmlns:jms="http://www.springframework.org/schema/integration/jms"
|
|
xmlns:mail="http://www.springframework.org/schema/integration/mail"
|
|
xmlns:rmi="http://www.springframework.org/schema/integration/rmi"
|
|
xmlns:ws="http://www.springframework.org/schema/integration/ws"
|
|
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
|
|
http://www.springframework.org/schema/integration/file
|
|
http://www.springframework.org/schema/integration/file/spring-integration-file-1.0.xsd
|
|
http://www.springframework.org/schema/integration/jms
|
|
http://www.springframework.org/schema/integration/jms/spring-integration-jms-1.0.xsd
|
|
http://www.springframework.org/schema/integration/mail
|
|
http://www.springframework.org/schema/integration/mail/spring-integration-mail-1.0.xsd
|
|
http://www.springframework.org/schema/integration/rmi
|
|
http://www.springframework.org/schema/integration/rmi/spring-integration-rmi-1.0.xsd
|
|
http://www.springframework.org/schema/integration/ws
|
|
http://www.springframework.org/schema/integration/ws/spring-integration-ws-1.0.xsd">
|
|
...
|
|
</beans>]]></programlisting>
|
|
The reference manual provides specific examples of the various elements in their corresponding chapters. Here, the
|
|
main thing to recognize is the consistency of the naming for each namespace URI and schema location.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="namespace-taskscheduler">
|
|
<title>Configuring the Task Scheduler</title>
|
|
<para>
|
|
In Spring Integration, the ApplicationContext plays the central role of a Message Bus, and there are only a
|
|
couple configuration options to be aware of. First, you may want to control the central TaskScheduler instance.
|
|
You can do so by providing a single bean with the name "taskScheduler". This is also defined as a constant:
|
|
<programlisting><![CDATA[ IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME ]]></programlisting>
|
|
By default Spring Integration uses the <classname>SimpleTaskScheduler</classname> implementation. That in turn
|
|
just delegates to any instance of Spring's <interfacename>TaskExecutor</interfacename> abstraction. Therefore,
|
|
it's rather trivial to supply your own configuration. The "taskScheduler" bean is then responsible for managing
|
|
all pollers. The TaskScheduler will startup automatically by default. If you provide your own instance of
|
|
SimpleTaskScheduler however, you can set the 'autoStartup' property to <emphasis>false</emphasis> instead.
|
|
</para>
|
|
<para>
|
|
When the endpoints are concurrency-enabled with their own 'taskExecutor' reference, the invocation of the
|
|
handling methods will happen within that executor's thread pool and not the main scheduler pool. However,
|
|
when no task-executor is provided for an endpoint's poller, it will be invoked in the dispatcher's thread
|
|
(with the exception of subscribable channels where the subscribers will be invoked directly). The next
|
|
section will describe what happens if Exceptions occur within the asynchronous invocations.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="namespace-errorhandler">
|
|
<title>Error Handling</title>
|
|
<para>
|
|
As described in the overview at the very beginning of this manual, one of the main motivations behind a
|
|
Message-oriented framework like Spring Integration is to promote loose-coupling between components. The
|
|
Message Channel plays an important role in that producers and consumers do not have to know about each
|
|
other. However, the advantages also have some drawbacks. Some things become more complicated in a very
|
|
loosely coupled environment, and one example is error handling.
|
|
</para>
|
|
<para>
|
|
When sending a Message to a channel, the component that ultimately handles that Message may or may not
|
|
be operating within the same thread as the sender. If using a simple default DirectChannel (with the
|
|
<channel> element that has no <queue> sub-element), the handling will be in the same thread.
|
|
In that case, if an Exception is thrown, it will be catch-able by the sender (or it may propagate past
|
|
the sender if it is an uncaught RuntimeException). So far, everything is fine. This is the same behavior
|
|
as an Exception-throwing operation in a normal call stack. However, when adding the asynchronous aspect,
|
|
things become much more complicated. For instance, if the 'channel' element <emphasis>does</emphasis>
|
|
provide a 'queue' sub-element, then the component that handles the Message <emphasis>will</emphasis> be
|
|
operating in a different thread than the sender. The sender may have dropped the Message and moved on to
|
|
other things. There is no way for the Exception to be thrown directly back to that sender using standard
|
|
Exception throwing techniques. Instead, to handle errors for asynchronous processes requires an
|
|
asynchronous error-handling mechanism as well.
|
|
</para>
|
|
<para>
|
|
Spring Integration supports error handling for its components by publishing errors to a Message Channel.
|
|
Specifically, the Exception will become the payload of a Spring Integration Message. That Message will
|
|
then be sent to a Message Channel that is resolved in a way that is very similar to the 'replyChannel'
|
|
resolution. First, if the request Message being handled at the time the Exception occurred contains
|
|
an 'errorChannel' header (the header name is defined in the constant: MessageHeaders.ERROR_CHANNEL),
|
|
the ErrorMessage will be sent to that channel. Otherwise, the error handler will send to a "global"
|
|
channel whose bean name is "errorChannel" (this is also defined as a constant:
|
|
IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME).
|
|
</para>
|
|
<para>
|
|
Whenever relying on Spring Integration's XML namespace support, a default "errorChannel" bean will be
|
|
created behind the scenes. However, you can just as easily define your own if you want to control the
|
|
settings.
|
|
<programlisting language="xml"><![CDATA[ <channel id="errorChannel" capacity="500"/>]]></programlisting>
|
|
</para>
|
|
<para>
|
|
The most important thing to understand here is that the Messaging-based error handling will only apply
|
|
to Exceptions that are thrown by a Spring Integration task that is executing within a TaskExecutor.
|
|
This does <emphasis>not</emphasis> apply to Exceptions thrown by a handler that is operating within
|
|
the same thread as the sender (e.g. through a DirectChannel as described above). However, when
|
|
Exceptions occur in a scheduled poller task's execution, those exceptions will be wrapped in
|
|
<classname>ErrorMessages</classname> and sent to the 'errorChannel' by default. To enable global error
|
|
handling, simply register a handler on that channel. For example, you can configure Spring Integration's
|
|
<classname>ErrorMessageExceptionTypeRouter</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>
|
|
</section>
|
|
|
|
<section id="annotations">
|
|
<title>Annotation Support</title>
|
|
<para>
|
|
In addition to the XML namespace support for configuring Message Endpoints, it is also possible to use
|
|
annotations. First, Spring Integration provides the class-level <interfacename>@MessageEndpoint</interfacename>
|
|
as a <emphasis>stereotype</emphasis> annotation meaning that is itself annotated with Spring's @Component
|
|
annotation and therefore is recognized automatically as a bean definition when using Spring component-scanning.
|
|
</para>
|
|
<para>
|
|
Even more importantly are the various Method-level annotations that indicate the annotated method is capable of
|
|
handling a message. The following example demonstrates both:
|
|
<programlisting language="java">@MessageEndpoint
|
|
public class FooService {
|
|
|
|
@ServiceActivator
|
|
public void processMessage(Message message) {
|
|
...
|
|
}
|
|
}</programlisting>
|
|
</para>
|
|
<para>
|
|
Exactly what it means for the method to "handle" the Message depends on the particular annotation. The following
|
|
are available with Spring Integration, and the behavior of each is described in its own chapter or section within
|
|
this reference: @Transformer, @Router, @Splitter, @Aggregator, @ServiceActivator, and @ChannelAdapter.
|
|
</para>
|
|
<note>
|
|
The @MessageEndpoint is not required. If you want to configure a POJO reference from the "ref" attribute
|
|
of a <service-activator/> element, it is sufficient to provide the method-level annotations.
|
|
</note>
|
|
<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 language="java">public class FooService {
|
|
|
|
@Handler
|
|
public void bar(<emphasis>Foo foo</emphasis>) {
|
|
...
|
|
}
|
|
|
|
}</programlisting>
|
|
</para>
|
|
<para>
|
|
When the method parameter should be mapped from a value in the <classname>MessageHeader</classname>, another
|
|
option is to use the parameter-level <interfacename>@Header</interfacename> annotation. In general, methods
|
|
annotated with the Spring Integration annotations can either accept the <classname>Message</classname> itself, the
|
|
message payload, or a header value (with @Header) as the parameter. In fact, the method can accept a combination,
|
|
such as:
|
|
<programlisting language="java">public class FooService {
|
|
|
|
@ServiceActivator
|
|
public void bar(String payload, @Header("x") int valueX, @Header("y") int valueY) {
|
|
...
|
|
}
|
|
|
|
}</programlisting>
|
|
There is also a @Headers annotation that provides all of the Message headers as a Map:
|
|
<programlisting language="java">public class FooService {
|
|
|
|
@ServiceActivator
|
|
public void bar(String payload, @Headers Map<String, Object> headerMap) {
|
|
...
|
|
}
|
|
|
|
}</programlisting>
|
|
</para>
|
|
<para>
|
|
For several of these annotations, when a Message-handling 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 such an endpoint's output channel will be used if available, and the message header's REPLY_CHANNEL value
|
|
will be the fallback.
|
|
</para>
|
|
<para>
|
|
In addition to the examples shown here, these annotations also support inputChannel and outputChannel properties.
|
|
<programlisting language="java">public class FooService {
|
|
|
|
@ServiceActivator(inputChannel="input", outputChannel="output")
|
|
public void bar(String payload, @Headers Map<String, Object> headerMap) {
|
|
...
|
|
}
|
|
|
|
}</programlisting>
|
|
That provides a pure annotation-driven alternative to the XML configuration. However, it is generally recommended
|
|
to use XML for the endpoints, since it is easier to keep track of the overall configuration in a single, external
|
|
location (and besides the XML configuration is not very verbose). If you do prefer to provide channels with the
|
|
annotations however, you just need to enable a BeanPostProcessor. The following element should be added:
|
|
<programlisting language="xml"><![CDATA[ <annotation-config/> ]]></programlisting>
|
|
</para>
|
|
</section>
|
|
|
|
</appendix> |