From 8a84c7dd3eab9631a97f18b7f47307f1a658d6a7 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 19 Aug 2019 15:35:48 -0400 Subject: [PATCH] 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 --- src/reference/asciidoc/changes-4.3-5.0.adoc | 2 +- src/reference/asciidoc/channel.adoc | 2 +- src/reference/asciidoc/configuration.adoc | 75 --------------------- src/reference/asciidoc/error-handling.adoc | 72 ++++++++++++++++++++ src/reference/asciidoc/index-single.adoc | 3 + src/reference/asciidoc/index.adoc | 1 + src/reference/asciidoc/scatter-gather.adoc | 2 +- src/reference/asciidoc/whats-new.adoc | 2 +- 8 files changed, 80 insertions(+), 79 deletions(-) create mode 100644 src/reference/asciidoc/error-handling.adoc diff --git a/src/reference/asciidoc/changes-4.3-5.0.adoc b/src/reference/asciidoc/changes-4.3-5.0.adoc index 16762c0f008..0b1fa4a31ee 100644 --- a/src/reference/asciidoc/changes-4.3-5.0.adoc +++ b/src/reference/asciidoc/changes-4.3-5.0.adoc @@ -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 diff --git a/src/reference/asciidoc/channel.adoc b/src/reference/asciidoc/channel.adoc index 4b2ee295a82..4eb24fef91d 100644 --- a/src/reference/asciidoc/channel.adoc +++ b/src/reference/asciidoc/channel.adoc @@ -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. diff --git a/src/reference/asciidoc/configuration.adoc b/src/reference/asciidoc/configuration.adoc index 70dc26c1a0b..0dd26c2d228 100644 --- a/src/reference/asciidoc/configuration.adoc +++ b/src/reference/asciidoc/configuration.adoc @@ -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 `` element that has no `` 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] ----- - - - ----- -==== - -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 diff --git a/src/reference/asciidoc/error-handling.adoc b/src/reference/asciidoc/error-handling.adoc new file mode 100644 index 00000000000..9200afde298 --- /dev/null +++ b/src/reference/asciidoc/error-handling.adoc @@ -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 `` element that has no `` 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] +---- + + + +---- +==== + +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. diff --git a/src/reference/asciidoc/index-single.adoc b/src/reference/asciidoc/index-single.adoc index 3eb92a8e010..bace77b0402 100644 --- a/src/reference/asciidoc/index-single.adoc +++ b/src/reference/asciidoc/index-single.adoc @@ -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[] diff --git a/src/reference/asciidoc/index.adoc b/src/reference/asciidoc/index.adoc index 1d786360754..cc7847bd60b 100644 --- a/src/reference/asciidoc/index.adoc +++ b/src/reference/asciidoc/index.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>> :: diff --git a/src/reference/asciidoc/scatter-gather.adoc b/src/reference/asciidoc/scatter-gather.adoc index 55b83aef7bb..e791d230350 100644 --- a/src/reference/asciidoc/scatter-gather.adoc +++ b/src/reference/asciidoc/scatter-gather.adoc @@ -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. diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 9ee1a63b26b..0bd024e27b1 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -84,7 +84,7 @@ The `Function>` 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