Add after completion callbacks to ChannelInterceptor

Issue: SPR-11966
This commit is contained in:
Rossen Stoyanchev
2014-07-09 18:50:38 -04:00
parent 6f062581a6
commit eaad0a0f52
5 changed files with 277 additions and 148 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -29,6 +29,7 @@ import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
/**
* Test fixture for the use of {@link ChannelInterceptor}s.
@@ -51,45 +52,61 @@ public class ChannelInterceptorTests {
@Test
public void preSendInterceptorReturningModifiedMessage() {
this.channel.addInterceptor(new PreSendReturnsMessageInterceptor());
Message<?> expected = mock(Message.class);
PreSendInterceptor interceptor = new PreSendInterceptor();
interceptor.setMessageToReturn(expected);
this.channel.addInterceptor(interceptor);
this.channel.send(MessageBuilder.withPayload("test").build());
assertEquals(1, this.messageHandler.messages.size());
Message<?> result = this.messageHandler.messages.get(0);
assertEquals(1, this.messageHandler.getMessages().size());
Message<?> result = this.messageHandler.getMessages().get(0);
assertNotNull(result);
assertEquals("test", result.getPayload());
assertEquals(1, result.getHeaders().get(PreSendReturnsMessageInterceptor.class.getSimpleName()));
assertSame(expected, result);
assertTrue(interceptor.wasAfterCompletionInvoked());
}
@Test
public void preSendInterceptorReturningNull() {
PreSendReturnsNullInterceptor interceptor = new PreSendReturnsNullInterceptor();
this.channel.addInterceptor(interceptor);
PreSendInterceptor interceptor1 = new PreSendInterceptor();
NullReturningPreSendInterceptor interceptor2 = new NullReturningPreSendInterceptor();
this.channel.addInterceptor(interceptor1);
this.channel.addInterceptor(interceptor2);
Message<?> message = MessageBuilder.withPayload("test").build();
this.channel.send(message);
assertEquals(1, interceptor.counter.get());
assertEquals(0, this.messageHandler.messages.size());
assertEquals(1, interceptor1.getCounter().get());
assertEquals(1, interceptor2.getCounter().get());
assertEquals(0, this.messageHandler.getMessages().size());
assertTrue(interceptor1.wasAfterCompletionInvoked());
assertFalse(interceptor2.wasAfterCompletionInvoked());
}
@Test
public void postSendInterceptorMessageWasSent() {
final AtomicBoolean invoked = new AtomicBoolean(false);
final AtomicBoolean preSendInvoked = new AtomicBoolean(false);
final AtomicBoolean completionInvoked = new AtomicBoolean(false);
this.channel.addInterceptor(new ChannelInterceptorAdapter() {
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
assertInput(message, channel, sent);
preSendInvoked.set(true);
}
@Override
public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
assertInput(message, channel, sent);
completionInvoked.set(true);
}
private void assertInput(Message<?> message, MessageChannel channel, boolean sent) {
assertNotNull(message);
assertNotNull(channel);
assertSame(ChannelInterceptorTests.this.channel, channel);
assertTrue(sent);
invoked.set(true);
}
});
this.channel.send(MessageBuilder.withPayload("test").build());
assertTrue(invoked.get());
assertTrue(preSendInvoked.get());
assertTrue(completionInvoked.get());
}
@Test
@@ -100,19 +117,68 @@ public class ChannelInterceptorTests {
return false;
}
};
final AtomicBoolean invoked = new AtomicBoolean(false);
final AtomicBoolean preSendInvoked = new AtomicBoolean(false);
final AtomicBoolean completionInvoked = new AtomicBoolean(false);
testChannel.addInterceptor(new ChannelInterceptorAdapter() {
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
assertInput(message, channel, sent);
preSendInvoked.set(true);
}
@Override
public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
assertInput(message, channel, sent);
completionInvoked.set(true);
}
private void assertInput(Message<?> message, MessageChannel channel, boolean sent) {
assertNotNull(message);
assertNotNull(channel);
assertSame(testChannel, channel);
assertFalse(sent);
invoked.set(true);
}
});
testChannel.send(MessageBuilder.withPayload("test").build());
assertTrue(invoked.get());
assertTrue(preSendInvoked.get());
assertTrue(completionInvoked.get());
}
@Test
public void afterCompletionWithSendException() {
final AbstractMessageChannel testChannel = new AbstractMessageChannel() {
@Override
protected boolean sendInternal(Message<?> message, long timeout) {
throw new RuntimeException("Simulated exception");
}
};
PreSendInterceptor interceptor1 = new PreSendInterceptor();
PreSendInterceptor interceptor2 = new PreSendInterceptor();
testChannel.addInterceptor(interceptor1);
testChannel.addInterceptor(interceptor2);
try {
testChannel.send(MessageBuilder.withPayload("test").build());
}
catch (Exception ex) {
assertEquals("Simulated exception", ex.getCause().getMessage());
}
assertTrue(interceptor1.wasAfterCompletionInvoked());
assertTrue(interceptor2.wasAfterCompletionInvoked());
}
@Test
public void afterCompletionWithPreSendException() {
PreSendInterceptor interceptor1 = new PreSendInterceptor();
PreSendInterceptor interceptor2 = new PreSendInterceptor();
interceptor2.setExceptionToRaise(new RuntimeException("Simulated exception"));
this.channel.addInterceptor(interceptor1);
this.channel.addInterceptor(interceptor2);
try {
this.channel.send(MessageBuilder.withPayload("test").build());
}
catch (Exception ex) {
assertEquals("Simulated exception", ex.getCause().getMessage());
}
assertTrue(interceptor1.wasAfterCompletionInvoked());
assertFalse(interceptor2.wasAfterCompletionInvoked());
}
@@ -120,32 +186,75 @@ public class ChannelInterceptorTests {
private List<Message<?>> messages = new ArrayList<Message<?>>();
public List<Message<?>> getMessages() {
return this.messages;
}
@Override
public void handleMessage(Message<?> message) throws MessagingException {
this.messages.add(message);
this.getMessages().add(message);
}
}
private static class PreSendReturnsMessageInterceptor extends ChannelInterceptorAdapter {
private abstract static class AbstractTestInterceptor extends ChannelInterceptorAdapter {
private AtomicInteger counter = new AtomicInteger();
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
assertNotNull(message);
return MessageBuilder.fromMessage(message).setHeader(
this.getClass().getSimpleName(), counter.incrementAndGet()).build();
private volatile boolean afterCompletionInvoked;
public AtomicInteger getCounter() {
return this.counter;
}
}
private static class PreSendReturnsNullInterceptor extends ChannelInterceptorAdapter {
private AtomicInteger counter = new AtomicInteger();
public boolean wasAfterCompletionInvoked() {
return this.afterCompletionInvoked;
}
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
assertNotNull(message);
counter.incrementAndGet();
return message;
}
@Override
public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
this.afterCompletionInvoked = true;
}
}
private static class PreSendInterceptor extends AbstractTestInterceptor {
private Message<?> messageToReturn;
private RuntimeException exceptionToRaise;
public void setMessageToReturn(Message<?> messageToReturn) {
this.messageToReturn = messageToReturn;
}
public void setExceptionToRaise(RuntimeException exception) {
this.exceptionToRaise = exception;
}
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
super.preSend(message, channel);
if (this.exceptionToRaise != null) {
throw this.exceptionToRaise;
}
return (this.messageToReturn != null ? this.messageToReturn : message);
}
}
private static class NullReturningPreSendInterceptor extends AbstractTestInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
super.preSend(message, channel);
return null;
}
}