diff --git a/spring-integration-core/src/main/java/org/springframework/integration/message/EnhancedErrorMessage.java b/spring-integration-core/src/main/java/org/springframework/integration/message/EnhancedErrorMessage.java deleted file mode 100644 index f1b5e399b2..0000000000 --- a/spring-integration-core/src/main/java/org/springframework/integration/message/EnhancedErrorMessage.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.message; - -import java.util.Map; - -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.support.ErrorMessage; - -/** - * An error message that is enhanced with a message that is available at the - * stack frame where the error message is generated. Typically this will be a - * message that begins a subflow, whereas if the {@link Throwable} payload is - * a {@link org.springframework.messaging.MessagingException}, its failedMessage - * property will contain the message at the point where the exception occurred. - * - * @author Gary Russell - * - * @since 4.3.10 - * - * @deprecated since 4.3.10 in favor of direct {@link ErrorMessage} usage since 5.0. - */ -@Deprecated -public class EnhancedErrorMessage extends ErrorMessage { - - private static final long serialVersionUID = 5857673472822628678L; - - private final Message originalMessage; - - public EnhancedErrorMessage(Message originalMessage, Throwable payload) { - super(payload); - this.originalMessage = originalMessage; - } - - public EnhancedErrorMessage(Message originalMessage, Throwable payload, MessageHeaders headers) { - super(payload, headers); - this.originalMessage = originalMessage; - } - - public EnhancedErrorMessage(Message originalMessage, Throwable payload, Map headers) { - super(payload, headers); - this.originalMessage = originalMessage; - } - - public Message getOriginalMessage() { - return this.originalMessage; - } - -} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultErrorMessageStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultErrorMessageStrategy.java index da5853e64d..a286b77924 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultErrorMessageStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultErrorMessageStrategy.java @@ -36,12 +36,9 @@ import org.springframework.messaging.support.ErrorMessage; public class DefaultErrorMessageStrategy implements ErrorMessageStrategy { @Override - @SuppressWarnings("deprecation") public ErrorMessage buildErrorMessage(Throwable throwable, AttributeAccessor attributes) { Object inputMessage = attributes.getAttribute(ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY); - return inputMessage instanceof Message - ? new org.springframework.integration.message.EnhancedErrorMessage((Message) inputMessage, throwable) - : new ErrorMessage(throwable); + return new ErrorMessage(throwable, inputMessage instanceof Message ? (Message) inputMessage : null); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/ErrorMessageStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/support/ErrorMessageStrategy.java index 0f540a997e..875721b7c4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/ErrorMessageStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/ErrorMessageStrategy.java @@ -35,6 +35,7 @@ import org.springframework.messaging.support.ErrorMessage; * * @since 4.3.10 */ +@FunctionalInterface public interface ErrorMessageStrategy { /** diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java index c0fee6969d..7e40b086f7 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java @@ -1034,24 +1034,21 @@ public class AdvisedMessageHandlerTests { } assertEquals(expected, counter.get()); - } @Test - @SuppressWarnings("deprecation") public void enhancedRecoverer() throws Exception { QueueChannel channel = new QueueChannel(); ErrorMessageSendingRecoverer recoverer = new ErrorMessageSendingRecoverer(channel); recoverer.publish(new GenericMessage<>("foo"), new GenericMessage<>("bar"), new RuntimeException("baz")); Message error = channel.receive(0); - assertThat(error, instanceOf(org.springframework.integration.message.EnhancedErrorMessage.class)); + assertThat(error, instanceOf(ErrorMessage.class)); assertThat(error.getPayload(), instanceOf(MessagingException.class)); MessagingException payload = (MessagingException) error.getPayload(); assertThat(payload.getCause(), instanceOf(RuntimeException.class)); assertThat(payload.getCause().getMessage(), equalTo("baz")); assertThat(payload.getFailedMessage().getPayload(), equalTo("bar")); - assertThat(((org.springframework.integration.message.EnhancedErrorMessage) error).getOriginalMessage() - .getPayload(), equalTo("foo")); + assertThat(((ErrorMessage) error).getOriginalMessage().getPayload(), equalTo("foo")); } private interface Bar { diff --git a/src/reference/asciidoc/configuration.adoc b/src/reference/asciidoc/configuration.adoc index b192d1df3d..c5acc407fa 100644 --- a/src/reference/asciidoc/configuration.adoc +++ b/src/reference/asciidoc/configuration.adoc @@ -195,6 +195,15 @@ To enable global error handling, simply 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 `Exception` type. +Starting with _version 4.3.10_, the `ErrorMessagePublisher` and the `ErrorMessageStrategy` are provided. +They can be used as general mechanism for publishing `ErrorMessage` s and can be called or extended in any error handling scenarios. +The `ErrorMessageSendingRecoverer` extends this class as a `RecoveryCallback` implementation that can be used with retry, such as the +<>. +The `ErrorMessageStrategy` is used to build an `ErrorMessage` based on the provided exception and an `AttributeAccessor` context. +It can be injected to any `MessageProducerSupport` and `MessagingGatewaySupport` - and 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. + [[global-properties]] === Global Properties diff --git a/src/reference/asciidoc/router.adoc b/src/reference/asciidoc/router.adoc index 106903ba29..287da543c9 100644 --- a/src/reference/asciidoc/router.adoc +++ b/src/reference/asciidoc/router.adoc @@ -1380,18 +1380,12 @@ public PollableChannel resultsChannel() { public RoutingSlipRouteStrategy routeStrategy() { return (requestMessage, reply) -> requestMessage.getPayload() instanceof String ? new FixedSubscriberChannel(m -> - Streams.defer((String) m.getPayload()) - .env(this.reactorEnv) - .get() + Mono.just((String) m.getPayload()) .map(String::toUpperCase) - .consume(v -> messagingTemplate().convertAndSend(resultsChannel(), v)) - .flush()) + .subscribe(v -> messagingTemplate().convertAndSend(resultsChannel(), v))) : new FixedSubscriberChannel(m -> - Streams.defer((Integer) m.getPayload()) - .env(this.reactorEnv) - .get() + Mono.just((Integer) m.getPayload()) .map(v -> v * 2) - .consume(v -> messagingTemplate().convertAndSend(resultsChannel(), v)) - .flush()); + .subscribe(v -> messagingTemplate().convertAndSend(resultsChannel(), v))); } ---- diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 1cb3cba0e1..c1c539edc1 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -37,11 +37,15 @@ See <> for more information. Now that we use the new `InvocableHandlerMethod` -based infrastructure for service method invocations, we can perform `contentType` conversion from payload to target method argument. See <> for more information. +==== ErrorMessagePublisher and ErrorMessageStrategy + +The `ErrorMessagePublisher` abd the `ErrorMessageStrategy` are provided for creating `ErrorMessage` instances. +See <> for more information. [[x5.0-general]] === General Changes -Spring Integration is now fully based on Spring Framework `5.0` and Project Reactor `3.0`. +Spring Integration is now fully based on Spring Framework `5.0` and Project Reactor `3.1`. Previous Project Reactor versions are no longer supported. ==== Core Changes