/*
* 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.
* 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.messaging.support;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for the use of {@link ChannelInterceptor}s.
*
* @author Rossen Stoyanchev
*/
public class ChannelInterceptorTests {
private ExecutorSubscribableChannel channel;
private TestMessageHandler messageHandler;
@Before
public void setup() {
this.channel = new ExecutorSubscribableChannel();
this.messageHandler = new TestMessageHandler();
this.channel.subscribe(this.messageHandler);
}
@Test
public void preSendInterceptorReturningModifiedMessage() {
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.getMessages().size());
Message<?> result = this.messageHandler.getMessages().get(0);
assertNotNull(result);
assertSame(expected, result);
assertTrue(interceptor.wasAfterCompletionInvoked());
}
@Test
public void preSendInterceptorReturningNull() {
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, 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 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);
}
});
this.channel.send(MessageBuilder.withPayload("test").build());
assertTrue(preSendInvoked.get());
assertTrue(completionInvoked.get());
}
@Test
public void postSendInterceptorMessageWasNotSent() {
final AbstractMessageChannel testChannel = new AbstractMessageChannel() {
@Override
protected boolean sendInternal(Message<?> message, long timeout) {
return 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);
}
});
testChannel.send(MessageBuilder.withPayload("test").build());
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());
}
private static class TestMessageHandler implements MessageHandler {
private final List<Message<?>> messages = new ArrayList<>();
public List<Message<?>> getMessages() {
return this.messages;
}
@Override
public void handleMessage(Message<?> message) throws MessagingException {
this.messages.add(message);
}
}
private abstract static class AbstractTestInterceptor extends ChannelInterceptorAdapter {
private AtomicInteger counter = new AtomicInteger();
private volatile boolean afterCompletionInvoked;
public AtomicInteger getCounter() {
return this.counter;
}
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;
}
}
}