View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.messaging.support;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.concurrent.atomic.AtomicBoolean;
22  import java.util.concurrent.atomic.AtomicInteger;
23  
24  import org.junit.Before;
25  import org.junit.Test;
26  
27  import org.springframework.messaging.Message;
28  import org.springframework.messaging.MessageChannel;
29  import org.springframework.messaging.MessageHandler;
30  import org.springframework.messaging.MessagingException;
31  
32  import static org.junit.Assert.*;
33  import static org.mockito.Mockito.*;
34  
35  /**
36   * Test fixture for the use of {@link ChannelInterceptor}s.
37   *
38   * @author Rossen Stoyanchev
39   */
40  public class ChannelInterceptorTests {
41  
42  	private ExecutorSubscribableChannel channel;
43  
44  	private TestMessageHandler messageHandler;
45  
46  
47  	@Before
48  	public void setup() {
49  		this.channel = new ExecutorSubscribableChannel();
50  		this.messageHandler = new TestMessageHandler();
51  		this.channel.subscribe(this.messageHandler);
52  	}
53  
54  
55  	@Test
56  	public void preSendInterceptorReturningModifiedMessage() {
57  		Message<?> expected = mock(Message.class);
58  		PreSendInterceptor interceptor = new PreSendInterceptor();
59  		interceptor.setMessageToReturn(expected);
60  		this.channel.addInterceptor(interceptor);
61  		this.channel.send(MessageBuilder.withPayload("test").build());
62  
63  		assertEquals(1, this.messageHandler.getMessages().size());
64  		Message<?> result = this.messageHandler.getMessages().get(0);
65  
66  		assertNotNull(result);
67  		assertSame(expected, result);
68  		assertTrue(interceptor.wasAfterCompletionInvoked());
69  	}
70  
71  	@Test
72  	public void preSendInterceptorReturningNull() {
73  		PreSendInterceptor interceptor1 = new PreSendInterceptor();
74  		NullReturningPreSendInterceptor interceptor2 = new NullReturningPreSendInterceptor();
75  		this.channel.addInterceptor(interceptor1);
76  		this.channel.addInterceptor(interceptor2);
77  		Message<?> message = MessageBuilder.withPayload("test").build();
78  		this.channel.send(message);
79  
80  		assertEquals(1, interceptor1.getCounter().get());
81  		assertEquals(1, interceptor2.getCounter().get());
82  		assertEquals(0, this.messageHandler.getMessages().size());
83  		assertTrue(interceptor1.wasAfterCompletionInvoked());
84  		assertFalse(interceptor2.wasAfterCompletionInvoked());
85  	}
86  
87  	@Test
88  	public void postSendInterceptorMessageWasSent() {
89  		final AtomicBoolean preSendInvoked = new AtomicBoolean(false);
90  		final AtomicBoolean completionInvoked = new AtomicBoolean(false);
91  		this.channel.addInterceptor(new ChannelInterceptorAdapter() {
92  			@Override
93  			public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
94  				assertInput(message, channel, sent);
95  				preSendInvoked.set(true);
96  			}
97  			@Override
98  			public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
99  				assertInput(message, channel, sent);
100 				completionInvoked.set(true);
101 			}
102 			private void assertInput(Message<?> message, MessageChannel channel, boolean sent) {
103 				assertNotNull(message);
104 				assertNotNull(channel);
105 				assertSame(ChannelInterceptorTests.this.channel, channel);
106 				assertTrue(sent);
107 			}
108 		});
109 		this.channel.send(MessageBuilder.withPayload("test").build());
110 		assertTrue(preSendInvoked.get());
111 		assertTrue(completionInvoked.get());
112 	}
113 
114 	@Test
115 	public void postSendInterceptorMessageWasNotSent() {
116 		final AbstractMessageChannel testChannel = new AbstractMessageChannel() {
117 			@Override
118 			protected boolean sendInternal(Message<?> message, long timeout) {
119 				return false;
120 			}
121 		};
122 		final AtomicBoolean preSendInvoked = new AtomicBoolean(false);
123 		final AtomicBoolean completionInvoked = new AtomicBoolean(false);
124 		testChannel.addInterceptor(new ChannelInterceptorAdapter() {
125 			@Override
126 			public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
127 				assertInput(message, channel, sent);
128 				preSendInvoked.set(true);
129 			}
130 			@Override
131 			public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
132 				assertInput(message, channel, sent);
133 				completionInvoked.set(true);
134 			}
135 			private void assertInput(Message<?> message, MessageChannel channel, boolean sent) {
136 				assertNotNull(message);
137 				assertNotNull(channel);
138 				assertSame(testChannel, channel);
139 				assertFalse(sent);
140 			}
141 		});
142 		testChannel.send(MessageBuilder.withPayload("test").build());
143 		assertTrue(preSendInvoked.get());
144 		assertTrue(completionInvoked.get());
145 	}
146 
147 	@Test
148 	public void afterCompletionWithSendException() {
149 		final AbstractMessageChannel testChannel = new AbstractMessageChannel() {
150 			@Override
151 			protected boolean sendInternal(Message<?> message, long timeout) {
152 				throw new RuntimeException("Simulated exception");
153 			}
154 		};
155 		PreSendInterceptor interceptor1 = new PreSendInterceptor();
156 		PreSendInterceptor interceptor2 = new PreSendInterceptor();
157 		testChannel.addInterceptor(interceptor1);
158 		testChannel.addInterceptor(interceptor2);
159 		try {
160 			testChannel.send(MessageBuilder.withPayload("test").build());
161 		}
162 		catch (Exception ex) {
163 			assertEquals("Simulated exception", ex.getCause().getMessage());
164 		}
165 		assertTrue(interceptor1.wasAfterCompletionInvoked());
166 		assertTrue(interceptor2.wasAfterCompletionInvoked());
167 	}
168 
169 	@Test
170 	public void afterCompletionWithPreSendException() {
171 		PreSendInterceptor interceptor1 = new PreSendInterceptor();
172 		PreSendInterceptor interceptor2 = new PreSendInterceptor();
173 		interceptor2.setExceptionToRaise(new RuntimeException("Simulated exception"));
174 		this.channel.addInterceptor(interceptor1);
175 		this.channel.addInterceptor(interceptor2);
176 		try {
177 			this.channel.send(MessageBuilder.withPayload("test").build());
178 		}
179 		catch (Exception ex) {
180 			assertEquals("Simulated exception", ex.getCause().getMessage());
181 		}
182 		assertTrue(interceptor1.wasAfterCompletionInvoked());
183 		assertFalse(interceptor2.wasAfterCompletionInvoked());
184 	}
185 
186 
187 	private static class TestMessageHandler implements MessageHandler {
188 
189 		private final List<Message<?>> messages = new ArrayList<Message<?>>();
190 
191 		public List<Message<?>> getMessages() {
192 			return this.messages;
193 		}
194 
195 		@Override
196 		public void handleMessage(Message<?> message) throws MessagingException {
197 			this.messages.add(message);
198 		}
199 	}
200 
201 
202 	private abstract static class AbstractTestInterceptor extends ChannelInterceptorAdapter {
203 
204 		private AtomicInteger counter = new AtomicInteger();
205 
206 		private volatile boolean afterCompletionInvoked;
207 
208 		public AtomicInteger getCounter() {
209 			return this.counter;
210 		}
211 
212 		public boolean wasAfterCompletionInvoked() {
213 			return this.afterCompletionInvoked;
214 		}
215 
216 		@Override
217 		public Message<?> preSend(Message<?> message, MessageChannel channel) {
218 			assertNotNull(message);
219 			counter.incrementAndGet();
220 			return message;
221 		}
222 
223 		@Override
224 		public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
225 			this.afterCompletionInvoked = true;
226 		}
227 	}
228 
229 
230 	private static class PreSendInterceptor extends AbstractTestInterceptor {
231 
232 		private Message<?> messageToReturn;
233 
234 		private RuntimeException exceptionToRaise;
235 
236 		public void setMessageToReturn(Message<?> messageToReturn) {
237 			this.messageToReturn = messageToReturn;
238 		}
239 
240 		public void setExceptionToRaise(RuntimeException exception) {
241 			this.exceptionToRaise = exception;
242 		}
243 
244 		@Override
245 		public Message<?> preSend(Message<?> message, MessageChannel channel) {
246 			super.preSend(message, channel);
247 			if (this.exceptionToRaise != null) {
248 				throw this.exceptionToRaise;
249 			}
250 			return (this.messageToReturn != null ? this.messageToReturn : message);
251 		}
252 	}
253 
254 
255 	private static class NullReturningPreSendInterceptor extends AbstractTestInterceptor {
256 
257 		@Override
258 		public Message<?> preSend(Message<?> message, MessageChannel channel) {
259 			super.preSend(message, channel);
260 			return null;
261 		}
262 	}
263 
264 }