GH-3024 Move Error Handling Docs to the top level
Fixes https://github.com/spring-projects/spring-integration/issues/3024 To avoid confusing about `errorChannel` header behavior and make it more clear how to handle errors in Spring Integration flows, it would be better to present an `Error Handling` chapter on the top level. So, now it is a first chapter of the `Appendices` section
This commit is contained in:
committed by
Gary Russell
parent
a835a63aad
commit
b7e928b846
@@ -45,7 +45,7 @@ See <<./endpoint.adoc#content-type-conversion,Content Type Conversion>> for more
|
||||
|
||||
We added `ErrorMessagePublisher` and the `ErrorMessageStrategy` for creating `ErrorMessage` instances.
|
||||
|
||||
See <<./configuration.adoc#namespace-errorhandler,Error Handling>> for more information.
|
||||
See <<./error-handling.adoc#error-handling,Error Handling>> for more information.
|
||||
|
||||
===== JDBC Metadata Store
|
||||
|
||||
|
||||
@@ -951,7 +951,7 @@ If namespace support is enabled, two special channels are defined within the app
|
||||
The 'nullChannel' acts like `/dev/null`, logging any message sent to it at the `DEBUG` level and returning immediately.
|
||||
Any time you face channel resolution errors for a reply that you do not care about, you can set the affected component's `output-channel` attribute to 'nullChannel' (the name, 'nullChannel', is reserved within the application context).
|
||||
The 'errorChannel' is used internally for sending error messages and may be overridden with a custom configuration.
|
||||
This is discussed in greater detail in <<./configuration.adoc#namespace-errorhandler,Error Handling>>.
|
||||
This is discussed in greater detail in <<./error-handling.adoc#error-handling,Error Handling>>.
|
||||
|
||||
|
||||
See also <<./dsl.adoc#java-dsl-channels,Message Channels>> in the Java DSL chapter for more information about message channel and interceptors.
|
||||
|
||||
@@ -149,81 +149,6 @@ To do so, define a bean with the appropriate JNDI name for your environment, as
|
||||
|
||||
The next section describes what happens if exceptions occur within the asynchronous invocations.
|
||||
|
||||
[[namespace-errorhandler]]
|
||||
=== Error Handling
|
||||
|
||||
As described in the <<./overview.adoc#overview,overview>> at the very beginning of this manual, one of the main motivations behind a message-oriented framework such as 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 loosely coupled environment, and one example is error handling.
|
||||
|
||||
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` (when the `<channel>` element that has no `<queue>` child element and no 'task-executor' attribute),
|
||||
the message handling occurs in the same thread that sends the initial message.
|
||||
In that case, if an `Exception` is thrown, it can be caught 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.
|
||||
|
||||
A message flow that runs on a caller thread might be invoked through a messaging gateway (see <<./gateway.adoc#gateway,Messaging Gateways>>) or a `MessagingTemplate` (see <<./channel.adoc#channel-template,`MessagingTemplate`>>).
|
||||
In either case, the default behavior is to throw any exceptions to the caller.
|
||||
For the messaging gateway, see <<./gateway.adoc#gateway-error-handling,Error Handling>> for details about how the exception is thrown and how to configure the gateway to route the errors to an error channel instead.
|
||||
When using a `MessagingTemplate` or sending to a `MessageChannel` directly, exceptions are always thrown to the caller.
|
||||
|
||||
When adding asynchronous processing, things become rather more complicated.
|
||||
For instance, if the 'channel' element does provide a 'queue' child element, the component that handles the message operates in a different thread than the sender.
|
||||
The same is true when an `ExecutorChannel` is used.
|
||||
The sender may have dropped the `Message` into the channel and moved on to other things.
|
||||
There is no way for the `Exception` to be thrown directly back to that sender by using standard `Exception` throwing techniques.
|
||||
Instead, handling errors for asynchronous processes requires that the error-handling mechanism also be asynchronous.
|
||||
|
||||
Spring Integration supports error handling for its components by publishing errors to a message channel.
|
||||
Specifically, the `Exception` becomes the payload of a Spring Integration `ErrorMessage`.
|
||||
That `Message` is then sent to a message channel that is resolved in a way that is 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 `MessageHeaders.ERROR_CHANNEL` constant), the `ErrorMessage` is sent to that channel.
|
||||
Otherwise, the error handler sends to a "`global`" channel whose bean name is `errorChannel` (this is also defined as a constant: `IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME`).
|
||||
|
||||
A default `errorChannel` bean is created internally by the Framework.
|
||||
However, you can define your own if you want to control the settings.
|
||||
The following example shows how to define an error channel backed by a queue with a capacity of 500:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:channel id="errorChannel">
|
||||
<int:queue capacity="500"/>
|
||||
</int:channel>
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: The default error channel is a `PublishSubscribeChannel`.
|
||||
|
||||
The most important thing to understand here is that the messaging-based error handling applies only to exceptions that are thrown by a Spring Integration task that is executing within a `TaskExecutor`.
|
||||
This does not apply to exceptions thrown by a handler that operates within the same thread as the sender (for example, through a `DirectChannel` as described earlier in this section).
|
||||
|
||||
NOTE: When exceptions occur in a scheduled poller task's execution, those exceptions are wrapped in `ErrorMessage` instances and sent to the 'errorChannel' as well.
|
||||
|
||||
To enable global error handling, register a handler on that channel.
|
||||
For example, you can configure Spring Integration's `ErrorMessageExceptionTypeRouter` 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 the `Exception` type.
|
||||
|
||||
Starting with version 4.3.10, Spring Integration provides the `ErrorMessagePublisher` and the `ErrorMessageStrategy`.
|
||||
You can use them as a general mechanism for publishing `ErrorMessage` instances.
|
||||
You can call or extend them in any error handling scenarios.
|
||||
The `ErrorMessageSendingRecoverer` extends this class as a `RecoveryCallback` implementation that can be used with retry, such as the
|
||||
<<./handler-advice.adoc#retry-advice,`RequestHandlerRetryAdvice`>>.
|
||||
The `ErrorMessageStrategy` is used to build an `ErrorMessage` based on the provided exception and an `AttributeAccessor` context.
|
||||
It can be injected into any `MessageProducerSupport` or `MessagingGatewaySupport`.
|
||||
The `requestMessage` is stored under `ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY` in the `AttributeAccessor` context.
|
||||
The `ErrorMessageStrategy` can use that `requestMessage` as the `originalMessage` property of the `ErrorMessage` it creates.
|
||||
The `DefaultErrorMessageStrategy` does exactly that.
|
||||
|
||||
Starting with version 5.2, all the `MessageHandlingException` instances thrown by the framework components, includes a component `BeanDefinition` resource and source to determine a configuration point form the exception.
|
||||
In case of XML configuration, a resource is an XML file path and source an XML tag with its `id` attribute.
|
||||
With Java & Annotation configuration, a resource is a `@Configuration` class and source is a `@Bean` method.
|
||||
In most case the target integration flow solution is based on the out-of-the-box components and their configuration options.
|
||||
When an exception happens at runtime, there is no any end-user code involved in stack trace because an execution is against beans, not their configuration.
|
||||
Including a resource and source of the bean definition helps to determine possible configuration mistakes and provides better developer experience.
|
||||
|
||||
[[global-properties]]
|
||||
=== Global Properties
|
||||
|
||||
|
||||
72
src/reference/asciidoc/error-handling.adoc
Normal file
72
src/reference/asciidoc/error-handling.adoc
Normal file
@@ -0,0 +1,72 @@
|
||||
[[error-handling]]
|
||||
== Error Handling
|
||||
|
||||
As described in the <<./overview.adoc#overview,overview>> at the very beginning of this manual, one of the main motivations behind a message-oriented framework such as 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 loosely coupled environment, and one example is error handling.
|
||||
|
||||
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` (when the `<channel>` element that has no `<queue>` child element and no 'task-executor' attribute), the message handling occurs in the same thread that sends the initial message.
|
||||
In that case, if an `Exception` is thrown, it can be caught by the sender (or it may propagate past the sender if it is an uncaught `RuntimeException`).
|
||||
This is the same behavior as an exception-throwing operation in a normal Java call stack.
|
||||
|
||||
A message flow that runs on a caller thread might be invoked through a messaging gateway (see <<./gateway.adoc#gateway,Messaging Gateways>>) or a `MessagingTemplate` (see <<./channel.adoc#channel-template,`MessagingTemplate`>>).
|
||||
In either case, the default behavior is to throw any exceptions to the caller.
|
||||
For the messaging gateway, see <<./gateway.adoc#gateway-error-handling,Error Handling>> for details about how the exception is thrown and how to configure the gateway to route the errors to an error channel instead.
|
||||
When using a `MessagingTemplate` or sending to a `MessageChannel` directly, exceptions are always thrown to the caller.
|
||||
|
||||
When adding asynchronous processing, things become rather more complicated.
|
||||
For instance, if the 'channel' element does provide a 'queue' child element (`QueueChannel` in Java & Annotations Configuration), the component that handles the message operates in a different thread than the sender.
|
||||
The same is true when an `ExecutorChannel` is used.
|
||||
The sender may have dropped the `Message` into the channel and moved on to other things.
|
||||
There is no way for the `Exception` to be thrown directly back to that sender by using standard `Exception` throwing techniques.
|
||||
Instead, handling errors for asynchronous processes requires that the error-handling mechanism also be asynchronous.
|
||||
|
||||
Spring Integration supports error handling for its components by publishing errors to a message channel.
|
||||
Specifically, the `Exception` becomes the payload of a Spring Integration `ErrorMessage`.
|
||||
That `Message` is then sent to a message channel that is resolved in a way that is 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 `MessageHeaders.ERROR_CHANNEL` constant), the `ErrorMessage` is sent to that channel.
|
||||
Otherwise, the error handler sends to a "`global`" channel whose bean name is `errorChannel` (this is also defined as a constant: `IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME`).
|
||||
|
||||
A default `errorChannel` bean is created internally by the Framework.
|
||||
However, you can define your own if you want to control the settings.
|
||||
The following example shows how to define an error channel in XML configuration backed by a queue with a capacity of `500`:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:channel id="errorChannel">
|
||||
<int:queue capacity="500"/>
|
||||
</int:channel>
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: The default error channel is a `PublishSubscribeChannel`.
|
||||
|
||||
The most important thing to understand here is that the messaging-based error handling applies only to exceptions that are thrown by a Spring Integration task that is executing within a `TaskExecutor`.
|
||||
This does not apply to exceptions thrown by a handler that operates within the same thread as the sender (for example, through a `DirectChannel` as described earlier in this section).
|
||||
|
||||
NOTE: When exceptions occur in a scheduled poller task's execution, those exceptions are wrapped in `ErrorMessage` instances and sent to the 'errorChannel' as well.
|
||||
|
||||
To enable global error handling, register a handler on that channel.
|
||||
For example, you can configure Spring Integration's `ErrorMessageExceptionTypeRouter` 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 the `Exception` type.
|
||||
|
||||
Starting with version 4.3.10, Spring Integration provides the `ErrorMessagePublisher` and the `ErrorMessageStrategy`.
|
||||
You can use them as a general mechanism for publishing `ErrorMessage` instances.
|
||||
You can call or extend them in any error handling scenarios.
|
||||
The `ErrorMessageSendingRecoverer` extends this class as a `RecoveryCallback` implementation that can be used with retry, such as the
|
||||
<<./handler-advice.adoc#retry-advice,`RequestHandlerRetryAdvice`>>.
|
||||
The `ErrorMessageStrategy` is used to build an `ErrorMessage` based on the provided exception and an `AttributeAccessor` context.
|
||||
It can be injected into any `MessageProducerSupport` or `MessagingGatewaySupport`.
|
||||
The `requestMessage` is stored under `ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY` in the `AttributeAccessor` context.
|
||||
The `ErrorMessageStrategy` can use that `requestMessage` as the `originalMessage` property of the `ErrorMessage` it creates.
|
||||
The `DefaultErrorMessageStrategy` does exactly that.
|
||||
|
||||
Starting with version 5.2, all the `MessageHandlingException` instances thrown by the framework components, includes a component `BeanDefinition` resource and source to determine a configuration point form the exception.
|
||||
In case of XML configuration, a resource is an XML file path and source an XML tag with its `id` attribute.
|
||||
With Java & Annotation configuration, a resource is a `@Configuration` class and source is a `@Bean` method.
|
||||
In most case the target integration flow solution is based on the out-of-the-box components and their configuration options.
|
||||
When an exception happens at runtime, there is no any end-user code involved in stack trace because an execution is against beans, not their configuration.
|
||||
Including a resource and source of the bean definition helps to determine possible configuration mistakes and provides better developer experience.
|
||||
@@ -89,6 +89,9 @@ The appendices cover advanced topics and additional resources.
|
||||
|
||||
The last appendix covers the history of Spring Integration.
|
||||
|
||||
[appendix]
|
||||
include::./error-handling.adoc[]
|
||||
|
||||
[appendix]
|
||||
include::./spel.adoc[]
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ as single searchable link:index-single.html[html] and link:../pdf/spring-integra
|
||||
**Appendices** ::
|
||||
|
||||
[horizontal]
|
||||
<<./error-handling.adoc#error-handling,Error Handling>> ::
|
||||
<<./spel.adoc#spel,Spring Expression Language (SpEL)>> ::
|
||||
<<./message-publishing.adoc#message-publishing,Message Publishing>> ::
|
||||
<<./transactions.adoc#transactions,Transaction Support>> ::
|
||||
|
||||
@@ -163,7 +163,7 @@ In other cases something like a "`compensation message`" should be considered fo
|
||||
|
||||
Every async sub-flow should be configured with a `errorChannel` header for the proper error message sending from the `MessagePublishingErrorHandler`.
|
||||
Otherwise, an error will be sent to the global `errorChannel` with the common error handling logic.
|
||||
See <<./configuration.adoc#namespace-errorhandler,Error Handling>> for more information about async error processing.
|
||||
See <<./error-handling.adoc#error-handling,Error Handling>> for more information about async error processing.
|
||||
|
||||
Synchronous flows may use an `ExpressionEvaluatingRequestHandlerAdvice` for ignoring the exception or returning a compensation message.
|
||||
When an exception is thrown from one of the sub-flows to the `ScatterGatherHandler`, it is just re-thrown to upstream.
|
||||
|
||||
@@ -84,7 +84,7 @@ The `Function<MessageGroup, Map<String, Object>>` strategy has been introduced f
|
||||
See <<./aggregator.adoc#aggregator-api,Aggregator Programming Model>> for more information.
|
||||
|
||||
All the `MessageHandlingException` s thrown in the framework, includes now a bean resource and source for back tracking a configuration part in case no end-user code involved.
|
||||
See <<./configuration.adoc#namespace-errorhandler,Error Handling>> for more information.
|
||||
See <<./error-handling.adoc#error-handling,Error Handling>> for more information.
|
||||
|
||||
[[x5.2-amqp]]
|
||||
==== AMQP Changes
|
||||
|
||||
Reference in New Issue
Block a user