INT-3943: AMQP Async Outbound Gateway
JIRA: https://jira.spring.io/browse/INT-3943 Initial commit. Polishing; Address PR Comments; Docs Doc Polishing Async GW - Support requiresReply Polishing. Avoid extra `requiresReply` in the `AsyncAmqpOutboundGateway`
This commit is contained in:
committed by
Artem Bilan
parent
78aaa6dac6
commit
d4e6615f82
@@ -32,6 +32,7 @@ import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.core.DestinationResolutionException;
|
||||
import org.springframework.messaging.support.ErrorMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
@@ -82,10 +83,19 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
protected void setAsyncReplySupported(boolean asyncReplySupported) {
|
||||
protected final void setAsyncReplySupported(boolean asyncReplySupported) {
|
||||
this.asyncReplySupported = asyncReplySupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setAsyncReplySupported(boolean)
|
||||
* @return true if this handler supports async replies.
|
||||
* @since 4.3
|
||||
*/
|
||||
protected boolean getAsyncReplySupported() {
|
||||
return this.asyncReplySupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
@@ -174,13 +184,18 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
|
||||
@Override
|
||||
public void onSuccess(Object result) {
|
||||
Message<?> replyMessage = null;
|
||||
try {
|
||||
sendOutput(createOutputMessage(result, requestHeaders), theReplyChannel, false);
|
||||
replyMessage = createOutputMessage(result, requestHeaders);
|
||||
sendOutput(replyMessage, theReplyChannel, false);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Exception exceptionToLogAndSend = e;
|
||||
if (!(e instanceof MessagingException)) {
|
||||
exceptionToLogAndSend = new MessageHandlingException(requestMessage, e);
|
||||
if (replyMessage != null) {
|
||||
exceptionToLogAndSend = new MessagingException(replyMessage, exceptionToLogAndSend);
|
||||
}
|
||||
}
|
||||
logger.error("Failed to send async reply: " + result.toString(), exceptionToLogAndSend);
|
||||
onFailure(exceptionToLogAndSend);
|
||||
@@ -200,7 +215,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
}
|
||||
else {
|
||||
try {
|
||||
sendOutput(createOutputMessage(result, requestHeaders), errorChannel, true);
|
||||
sendOutput(new ErrorMessage(result), errorChannel, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Exception exceptionToLog = e;
|
||||
@@ -254,7 +269,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
}
|
||||
}
|
||||
|
||||
private Message<?> createOutputMessage(Object output, MessageHeaders requestHeaders) {
|
||||
protected Message<?> createOutputMessage(Object output, MessageHeaders requestHeaders) {
|
||||
AbstractIntegrationMessageBuilder<?> builder = null;
|
||||
if (output instanceof Message<?>) {
|
||||
if (!this.shouldCopyRequestHeaders()) {
|
||||
@@ -280,12 +295,12 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
* <code>null</code>, and it must be an instance of either String or {@link MessageChannel}.
|
||||
* @param output the output object to send
|
||||
* @param replyChannel the 'replyChannel' value from the original request
|
||||
* @param isError - this is an error, use the replyChannel argument (must not be null), not
|
||||
* @param useArgChannel - use the replyChannel argument (must not be null), not
|
||||
* the configured output channel.
|
||||
*/
|
||||
private void sendOutput(Object output, Object replyChannel, boolean isError) {
|
||||
protected void sendOutput(Object output, Object replyChannel, boolean useArgChannel) {
|
||||
MessageChannel outputChannel = getOutputChannel();
|
||||
if (!isError && outputChannel != null) {
|
||||
if (!useArgChannel && outputChannel != null) {
|
||||
replyChannel = outputChannel;
|
||||
}
|
||||
if (replyChannel == null) {
|
||||
|
||||
@@ -57,6 +57,9 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
this.requiresReply = requiresReply;
|
||||
}
|
||||
|
||||
protected boolean getRequiresReply() {
|
||||
return requiresReply;
|
||||
}
|
||||
|
||||
public void setAdviceChain(List<Advice> adviceChain) {
|
||||
Assert.notNull(adviceChain, "adviceChain cannot be null");
|
||||
@@ -104,11 +107,11 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
|
||||
if (result != null) {
|
||||
sendOutputs(result, message);
|
||||
}
|
||||
else if (this.requiresReply) {
|
||||
else if (this.requiresReply && !getAsyncReplySupported()) {
|
||||
throw new ReplyRequiredException(message, "No reply produced by handler '" +
|
||||
getComponentName() + "', and its 'requiresReply' property is set to true.");
|
||||
}
|
||||
else if (logger.isDebugEnabled()) {
|
||||
else if (!getAsyncReplySupported() && logger.isDebugEnabled()) {
|
||||
logger.debug("handler '" + this + "' produced no reply for request Message: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -22,15 +22,30 @@ import org.springframework.messaging.MessagingException;
|
||||
/**
|
||||
* Exception that indicates no reply message is produced by a handler
|
||||
* that does have a value of true for the 'requiresReply' property.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ReplyRequiredException extends MessagingException {
|
||||
|
||||
/**
|
||||
* @param failedMessage the failed message.
|
||||
* @param description the description.
|
||||
*/
|
||||
public ReplyRequiredException(Message<?> failedMessage, String description) {
|
||||
super(failedMessage, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param failedMessage the failed message.
|
||||
* @param description the description.
|
||||
* @param t the root cause.
|
||||
* @since 4.3
|
||||
*/
|
||||
public ReplyRequiredException(Message<?> failedMessage, String description, Throwable t) {
|
||||
super(failedMessage, description, t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user