INT-2214, INT-343, INT-2250 MessageHandler Advice
Add general capability to advise just the handleRequestMessage part of an AbstractReplyProducingMessageHandler. This is to advise just the immediate operation, and not the entire downstream flow. Uses include: * outbound gateway post processing * adding retry behavior using spring-retry * adding circuit breaker functionality Initial commit for review. Also need to advise simple message handlers (such as file etc) to allow them to post-process file operations with payload.delete(), payload.renameTo(...) etc. INT-2250 Add Circuit Breaker Advice INT-343 Add Retry Advice Stateless and Stateful retry using spring-retry. Stateless means the RetryTemplate performs the retries internally. Stateful means the exception is thrown (e.g. to JMS container) and the retry state is maintained by spring-retry. INT-2215, INT-343, INT-2250 Refactoring Factor out common abstract Advice class. INT-2214 Catch Evaluation Expression Exceptions If an onSuccess expression evaluation fails, add an option so the user can decide whether such an exception is caught, or propagated to the caller. INT-2214 etc PR Review Polishing INT-2214 etc Namespace Core, File, FTP Add <request-handler-advice-chain/> to outbound endpoints. INT-2214 etc. More Namespace Support amqp, event, gemfire, groovy, http, ip, jdbc, jms, jmx, jpa, mail, rmi, sftp, twitter, ws, xmpp INT-2214 etc Polishing PR Review INT-2214 etc Polishing Don't catch Throwable. Move Advice classes to handler.advice package.
This commit is contained in:
committed by
Oleg Zhurakousky
parent
56e3c22970
commit
08cbab08c2
@@ -22,7 +22,11 @@
|
||||
<jmx:notification-publishing-channel-adapter
|
||||
id="adapter" channel="channel"
|
||||
object-name="test.publisher:name=publisher"
|
||||
default-notification-type="default.type"/>
|
||||
default-notification-type="default.type">
|
||||
<jmx:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.jmx.config.NotificationPublishingChannelAdapterParserTests$FooADvice" />
|
||||
</jmx:request-handler-advice-chain>
|
||||
</jmx:notification-publishing-channel-adapter>
|
||||
|
||||
|
||||
<si:chain input-channel="publishingWithinChainChannel">
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.jmx.JmxHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -36,6 +37,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@@ -51,6 +53,8 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private MessageChannel publishingWithinChainChannel;
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@After
|
||||
public void clearListener() {
|
||||
listener.lastNotification = null;
|
||||
@@ -59,6 +63,7 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void publishStringMessage() throws Exception {
|
||||
adviceCalled = 0;
|
||||
assertNull(listener.lastNotification);
|
||||
Message<?> message = MessageBuilder.withPayload("XYZ")
|
||||
.setHeader(JmxHeaders.NOTIFICATION_TYPE, "test.type").build();
|
||||
@@ -68,6 +73,7 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
assertEquals("XYZ", notification.getMessage());
|
||||
assertEquals("test.type", notification.getType());
|
||||
assertNull(notification.getUserData());
|
||||
assertEquals(1, adviceCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,4 +116,15 @@ public class NotificationPublishingChannelAdapterParserTests {
|
||||
private static class TestData {
|
||||
}
|
||||
|
||||
public static class FooADvice extends AbstractRequestHandlerAdvice {
|
||||
|
||||
@Override
|
||||
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
|
||||
adviceCalled++;
|
||||
System.out.println("foo");
|
||||
new RuntimeException("foo").printStackTrace();
|
||||
return callback.execute();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
<jmx:operation-invoking-channel-adapter id="input"
|
||||
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter"
|
||||
operation-name="test"/>
|
||||
operation-name="test">
|
||||
<jmx:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.jmx.config.OperationInvokingChannelAdapterParserTests$FooADvice" />
|
||||
</jmx:request-handler-advice-chain>
|
||||
</jmx:operation-invoking-channel-adapter>
|
||||
|
||||
<jmx:operation-invoking-channel-adapter id="operationWithNonNullReturn"
|
||||
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter"
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.jmx.JmxHeaders;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
@@ -58,6 +59,8 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private TestBean testBean;
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@After
|
||||
public void resetLists() {
|
||||
testBean.messages.clear();
|
||||
@@ -71,6 +74,7 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
input.send(new GenericMessage<String>("test2"));
|
||||
input.send(new GenericMessage<String>("test3"));
|
||||
assertEquals(3, testBean.messages.size());
|
||||
assertEquals(3, adviceCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,4 +122,14 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
.setHeader(JmxHeaders.OBJECT_NAME, "org.springframework.integration.jmx.config:type=TestBean,name=foo")
|
||||
.setHeader(JmxHeaders.OPERATION_NAME, "blah").build();
|
||||
}
|
||||
|
||||
public static class FooADvice extends AbstractRequestHandlerAdvice {
|
||||
|
||||
@Override
|
||||
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
|
||||
adviceCalled++;
|
||||
return callback.execute();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
<jmx:operation-invoking-outbound-gateway request-channel="withReplyChannel"
|
||||
reply-channel="withReplyChannelOutput"
|
||||
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanGateway"
|
||||
operation-name="testWithReturn"/>
|
||||
operation-name="testWithReturn">
|
||||
<jmx:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.jmx.config.OperationInvokingOutboundGatewayTests$FooADvice" />
|
||||
</jmx:request-handler-advice-chain>
|
||||
</jmx:operation-invoking-outbound-gateway>
|
||||
|
||||
<si:chain input-channel="jmxOutboundGatewayInsideChain" output-channel="withReplyChannelOutput">
|
||||
<jmx:operation-invoking-outbound-gateway operation-name="testWithReturn"
|
||||
|
||||
@@ -25,8 +25,10 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -59,6 +61,8 @@ public class OperationInvokingOutboundGatewayTests {
|
||||
@Autowired
|
||||
private TestBean testBean;
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@After
|
||||
public void resetLists() {
|
||||
testBean.messages.clear();
|
||||
@@ -72,6 +76,7 @@ public class OperationInvokingOutboundGatewayTests {
|
||||
assertEquals(2, ((List<?>) withReplyChannelOutput.receive().getPayload()).size());
|
||||
withReplyChannel.send(new GenericMessage<String>("3"));
|
||||
assertEquals(3, ((List<?>) withReplyChannelOutput.receive().getPayload()).size());
|
||||
assertEquals(3, adviceCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,4 +99,13 @@ public class OperationInvokingOutboundGatewayTests {
|
||||
assertEquals(3, ((List<?>) withReplyChannelOutput.receive().getPayload()).size());
|
||||
}
|
||||
|
||||
public static class FooADvice extends AbstractRequestHandlerAdvice {
|
||||
|
||||
@Override
|
||||
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
|
||||
adviceCalled++;
|
||||
return callback.execute();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user