From 0c14aa052ba44aa8a86298b563c58c8b334dbbf0 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 25 Oct 2018 13:10:23 -0400 Subject: [PATCH] INT-2416: Clarify copyHeaders in s-a.adoc JIRA: https://jira.spring.io/browse/INT-2416 Polishing --- src/reference/asciidoc/service-activator.adoc | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/reference/asciidoc/service-activator.adoc b/src/reference/asciidoc/service-activator.adoc index 77f0d5619e..05debb47f3 100644 --- a/src/reference/asciidoc/service-activator.adoc +++ b/src/reference/asciidoc/service-activator.adoc @@ -153,14 +153,26 @@ See <> in the Java DSL chapter for more information about confi ==== Asynchronous Service Activator The service activator is invoked by the calling thread. -This is an upstream thread if the input channel is a -`SubscribableChannel` or a poller thread for a `PollableChannel`. -If the service returns a `ListenableFuture`, the default action is to send that as the payload of the message sent -to the output (or reply) channel. -Starting with version 4.3, you can now set the `async` attribute to `true` (by using `setAsync(true)` when using -Java configuration). +This is an upstream thread if the input channel is a `SubscribableChannel` or a poller thread for a `PollableChannel`. +If the service returns a `ListenableFuture`, the default action is to send that as the payload of the message sent to the output (or reply) channel. +Starting with version 4.3, you can now set the `async` attribute to `true` (by using `setAsync(true)` when using Java configuration). If the service returns a `ListenableFuture` when this the `async` attribute is set to `true`, the calling thread is released immediately and the reply message is sent on the thread (from within your service) that completes the future. -This is particularly advantageous for long-running services that use a `PollableChannel`, because the poller thread is -released to perform other services within the framework. +This is particularly advantageous for long-running services that use a `PollableChannel`, because the poller thread is released to perform other services within the framework. -If the service completes the future with an `Exception`, normal error processing occurs. An `ErrorMessage` is sent to the `errorChannel` message header, if present. Otherwise, an `ErrorMessage` is sent to the default `errorChannel` (if available). +If the service completes the future with an `Exception`, normal error processing occurs. +An `ErrorMessage` is sent to the `errorChannel` message header, if present. Otherwise, an `ErrorMessage` is sent to the default `errorChannel` (if available). + + +[[service-activator-return-type]] +==== Service Activator and Method Return Type + +The service method can return any type which becomes reply message payload. +In this case a new `Message` object is created and all the headers from a request message are copied. +This works the same way for most Spring Integration `MessageHandler` implementations, when interaction is based on a POJO method invocation. + +A complete `Message` object can also be returned from the method. +However keep in mind that, unlike <>, for a Service Activator this message will be modified by copying the headers from the request message if they are not already present in the returned message. +So, if your method parameter is a `Message` and you copy some, but not all, existing headers in your service method, they will reappear in the reply message. +It is not a Service Activator responsibility to remove headers from a reply message and, pursuing the loosely-coupled principle, it is better to add a `HeaderFilter` in the integration flow. +Alternatively, a Transformer can be used instead of a Service Activator but, in that case, when returning a full `Message` the method is completely responsible for the message, including copying request message headers (if needed). +It is important to ensure that important framework headers (e.g. `replyChannel`, `errorChannel`), if present, must be preserved.