Added discussion of error handling (INT-457).
This commit is contained in:
@@ -91,8 +91,8 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="namespace-messagebus">
|
||||
<title>Configuring the Message Bus</title>
|
||||
<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.
|
||||
@@ -108,20 +108,61 @@
|
||||
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).
|
||||
(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>
|
||||
The Message Bus supports error handling for its components in the form of a configurable error channel,
|
||||
and it will first check for a channel bean named "errorChannel" within the context:
|
||||
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>
|
||||
When exceptions occur in a scheduled poller task's execution, those exceptions will be wrapped in
|
||||
</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. However, since most of the errors will already have been wrapped in
|
||||
<classname>MessageDeliveryException</classname> or <classname>MessageHandlingException</classname>,
|
||||
the <classname>ErrorMessageExceptionTypeRouter</classname> is typically a better option.
|
||||
<classname>Exception</classname> type.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user