1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.socket.config;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22
23 import org.hamcrest.Matchers;
24 import org.junit.Before;
25 import org.junit.Test;
26
27 import org.springframework.beans.DirectFieldAccessor;
28 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
29 import org.springframework.beans.factory.config.CustomScopeConfigurer;
30 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
31 import org.springframework.core.MethodParameter;
32 import org.springframework.core.io.ClassPathResource;
33 import org.springframework.messaging.Message;
34 import org.springframework.messaging.MessageHandler;
35 import org.springframework.messaging.converter.ByteArrayMessageConverter;
36 import org.springframework.messaging.converter.CompositeMessageConverter;
37 import org.springframework.messaging.converter.ContentTypeResolver;
38 import org.springframework.messaging.converter.DefaultContentTypeResolver;
39 import org.springframework.messaging.converter.MappingJackson2MessageConverter;
40 import org.springframework.messaging.converter.MessageConverter;
41 import org.springframework.messaging.converter.StringMessageConverter;
42 import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
43 import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
44 import org.springframework.messaging.simp.SimpMessagingTemplate;
45 import org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler;
46 import org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler;
47 import org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler;
48 import org.springframework.messaging.simp.user.DefaultUserDestinationResolver;
49 import org.springframework.messaging.simp.user.UserDestinationMessageHandler;
50 import org.springframework.messaging.simp.user.UserDestinationResolver;
51 import org.springframework.messaging.simp.user.UserSessionRegistry;
52 import org.springframework.messaging.support.AbstractSubscribableChannel;
53 import org.springframework.messaging.support.ChannelInterceptor;
54 import org.springframework.messaging.support.ImmutableMessageChannelInterceptor;
55 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
56 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
57 import org.springframework.util.MimeTypeUtils;
58 import org.springframework.web.HttpRequestHandler;
59 import org.springframework.web.context.support.GenericWebApplicationContext;
60 import org.springframework.web.servlet.HandlerMapping;
61 import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
62 import org.springframework.web.socket.WebSocketHandler;
63 import org.springframework.web.socket.WebSocketSession;
64 import org.springframework.web.socket.handler.TestWebSocketSession;
65 import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
66 import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
67 import org.springframework.web.socket.messaging.StompSubProtocolHandler;
68 import org.springframework.web.socket.messaging.SubProtocolWebSocketHandler;
69 import org.springframework.web.socket.server.HandshakeHandler;
70 import org.springframework.web.socket.server.HandshakeInterceptor;
71 import org.springframework.web.socket.server.support.OriginHandshakeInterceptor;
72 import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
73 import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
74 import org.springframework.web.socket.sockjs.transport.TransportType;
75 import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
76 import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
77
78 import static org.hamcrest.Matchers.*;
79 import static org.junit.Assert.*;
80
81
82
83
84
85
86
87
88
89 public class MessageBrokerBeanDefinitionParserTests {
90
91 private GenericWebApplicationContext appContext;
92
93
94 @Before
95 public void setup() {
96 this.appContext = new GenericWebApplicationContext();
97 }
98
99
100 @Test
101 public void simpleBroker() throws Exception {
102 loadBeanDefinitions("websocket-config-broker-simple.xml");
103
104 HandlerMapping hm = this.appContext.getBean(HandlerMapping.class);
105 assertThat(hm, Matchers.instanceOf(SimpleUrlHandlerMapping.class));
106 SimpleUrlHandlerMapping suhm = (SimpleUrlHandlerMapping) hm;
107 assertThat(suhm.getUrlMap().keySet(), Matchers.hasSize(4));
108 assertThat(suhm.getUrlMap().values(), Matchers.hasSize(4));
109
110 HttpRequestHandler httpRequestHandler = (HttpRequestHandler) suhm.getUrlMap().get("/foo");
111 assertNotNull(httpRequestHandler);
112 assertThat(httpRequestHandler, Matchers.instanceOf(WebSocketHttpRequestHandler.class));
113
114 WebSocketHttpRequestHandler wsHttpRequestHandler = (WebSocketHttpRequestHandler) httpRequestHandler;
115 HandshakeHandler handshakeHandler = wsHttpRequestHandler.getHandshakeHandler();
116 assertNotNull(handshakeHandler);
117 assertTrue(handshakeHandler instanceof TestHandshakeHandler);
118 List<HandshakeInterceptor> interceptors = wsHttpRequestHandler.getHandshakeInterceptors();
119 assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class),
120 instanceOf(BarTestInterceptor.class), instanceOf(OriginHandshakeInterceptor.class)));
121
122 WebSocketSession session = new TestWebSocketSession("id");
123 wsHttpRequestHandler.getWebSocketHandler().afterConnectionEstablished(session);
124 assertEquals(true, session.getAttributes().get("decorated"));
125
126 WebSocketHandler wsHandler = unwrapWebSocketHandler(wsHttpRequestHandler.getWebSocketHandler());
127 assertNotNull(wsHandler);
128 assertThat(wsHandler, Matchers.instanceOf(SubProtocolWebSocketHandler.class));
129
130 SubProtocolWebSocketHandler subProtocolWsHandler = (SubProtocolWebSocketHandler) wsHandler;
131 assertEquals(Arrays.asList("v10.stomp", "v11.stomp", "v12.stomp"), subProtocolWsHandler.getSubProtocols());
132 assertEquals(25 * 1000, subProtocolWsHandler.getSendTimeLimit());
133 assertEquals(1024 * 1024, subProtocolWsHandler.getSendBufferSizeLimit());
134
135 StompSubProtocolHandler stompHandler = (StompSubProtocolHandler) subProtocolWsHandler.getProtocolHandlerMap().get("v12.stomp");
136 assertNotNull(stompHandler);
137 assertEquals(128 * 1024, stompHandler.getMessageSizeLimit());
138
139 assertNotNull(new DirectFieldAccessor(stompHandler).getPropertyValue("eventPublisher"));
140
141 httpRequestHandler = (HttpRequestHandler) suhm.getUrlMap().get("/test/**");
142 assertNotNull(httpRequestHandler);
143 assertThat(httpRequestHandler, Matchers.instanceOf(SockJsHttpRequestHandler.class));
144
145 SockJsHttpRequestHandler sockJsHttpRequestHandler = (SockJsHttpRequestHandler) httpRequestHandler;
146 wsHandler = unwrapWebSocketHandler(sockJsHttpRequestHandler.getWebSocketHandler());
147 assertNotNull(wsHandler);
148 assertThat(wsHandler, Matchers.instanceOf(SubProtocolWebSocketHandler.class));
149 assertNotNull(sockJsHttpRequestHandler.getSockJsService());
150 assertThat(sockJsHttpRequestHandler.getSockJsService(), Matchers.instanceOf(DefaultSockJsService.class));
151
152 DefaultSockJsService defaultSockJsService = (DefaultSockJsService) sockJsHttpRequestHandler.getSockJsService();
153 WebSocketTransportHandler wsTransportHandler = (WebSocketTransportHandler) defaultSockJsService
154 .getTransportHandlers().get(TransportType.WEBSOCKET);
155 assertNotNull(wsTransportHandler.getHandshakeHandler());
156 assertThat(wsTransportHandler.getHandshakeHandler(), Matchers.instanceOf(TestHandshakeHandler.class));
157 assertFalse(defaultSockJsService.shouldSuppressCors());
158
159 ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler) defaultSockJsService.getTaskScheduler();
160 assertEquals(Runtime.getRuntime().availableProcessors(), scheduler.getScheduledThreadPoolExecutor().getCorePoolSize());
161 assertTrue(scheduler.getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy());
162
163 interceptors = defaultSockJsService.getHandshakeInterceptors();
164 assertThat(interceptors, contains(instanceOf(FooTestInterceptor.class),
165 instanceOf(BarTestInterceptor.class), instanceOf(OriginHandshakeInterceptor.class)));
166 assertEquals(Arrays.asList("http://mydomain3.com", "http://mydomain4.com"), defaultSockJsService.getAllowedOrigins());
167
168 UserSessionRegistry userSessionRegistry = this.appContext.getBean(UserSessionRegistry.class);
169 assertNotNull(userSessionRegistry);
170
171 UserDestinationResolver userDestResolver = this.appContext.getBean(UserDestinationResolver.class);
172 assertNotNull(userDestResolver);
173 assertThat(userDestResolver, Matchers.instanceOf(DefaultUserDestinationResolver.class));
174 DefaultUserDestinationResolver defaultUserDestResolver = (DefaultUserDestinationResolver) userDestResolver;
175 assertEquals("/personal/", defaultUserDestResolver.getDestinationPrefix());
176 assertSame(stompHandler.getUserSessionRegistry(), defaultUserDestResolver.getUserSessionRegistry());
177
178 UserDestinationMessageHandler userDestHandler = this.appContext.getBean(UserDestinationMessageHandler.class);
179 assertNotNull(userDestHandler);
180
181 SimpleBrokerMessageHandler brokerMessageHandler = this.appContext.getBean(SimpleBrokerMessageHandler.class);
182 assertNotNull(brokerMessageHandler);
183 assertEquals(Arrays.asList("/topic", "/queue"),
184 new ArrayList<String>(brokerMessageHandler.getDestinationPrefixes()));
185
186 List<Class<? extends MessageHandler>> subscriberTypes =
187 Arrays.<Class<? extends MessageHandler>>asList(SimpAnnotationMethodMessageHandler.class,
188 UserDestinationMessageHandler.class, SimpleBrokerMessageHandler.class);
189 testChannel("clientInboundChannel", subscriberTypes, 2);
190 testExecutor("clientInboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
191
192 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SubProtocolWebSocketHandler.class);
193 testChannel("clientOutboundChannel", subscriberTypes, 1);
194 testExecutor("clientOutboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
195
196 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SimpleBrokerMessageHandler.class, UserDestinationMessageHandler.class);
197 testChannel("brokerChannel", subscriberTypes, 1);
198 try {
199 this.appContext.getBean("brokerChannelExecutor", ThreadPoolTaskExecutor.class);
200 fail("expected exception");
201 }
202 catch (NoSuchBeanDefinitionException ex) {
203
204 }
205
206 assertNotNull(this.appContext.getBean("webSocketScopeConfigurer", CustomScopeConfigurer.class));
207
208 DirectFieldAccessor subscriptionRegistryAccessor = new DirectFieldAccessor(brokerMessageHandler.getSubscriptionRegistry());
209 String pathSeparator = (String)new DirectFieldAccessor(subscriptionRegistryAccessor.getPropertyValue("pathMatcher")).getPropertyValue("pathSeparator");
210 assertEquals(".", pathSeparator);
211 }
212
213 @Test
214 public void stompBrokerRelay() {
215 loadBeanDefinitions("websocket-config-broker-relay.xml");
216
217 HandlerMapping hm = this.appContext.getBean(HandlerMapping.class);
218 assertNotNull(hm);
219 assertThat(hm, Matchers.instanceOf(SimpleUrlHandlerMapping.class));
220
221 SimpleUrlHandlerMapping suhm = (SimpleUrlHandlerMapping) hm;
222 assertThat(suhm.getUrlMap().keySet(), Matchers.hasSize(1));
223 assertThat(suhm.getUrlMap().values(), Matchers.hasSize(1));
224 assertEquals(2, suhm.getOrder());
225
226 HttpRequestHandler httpRequestHandler = (HttpRequestHandler) suhm.getUrlMap().get("/foo/**");
227 assertNotNull(httpRequestHandler);
228 assertThat(httpRequestHandler, Matchers.instanceOf(SockJsHttpRequestHandler.class));
229 SockJsHttpRequestHandler sockJsHttpRequestHandler = (SockJsHttpRequestHandler) httpRequestHandler;
230 WebSocketHandler wsHandler = unwrapWebSocketHandler(sockJsHttpRequestHandler.getWebSocketHandler());
231 assertNotNull(wsHandler);
232 assertThat(wsHandler, Matchers.instanceOf(SubProtocolWebSocketHandler.class));
233 assertNotNull(sockJsHttpRequestHandler.getSockJsService());
234
235 UserDestinationResolver userDestResolver = this.appContext.getBean(UserDestinationResolver.class);
236 assertNotNull(userDestResolver);
237 assertThat(userDestResolver, Matchers.instanceOf(DefaultUserDestinationResolver.class));
238 DefaultUserDestinationResolver defaultUserDestResolver = (DefaultUserDestinationResolver) userDestResolver;
239 assertEquals("/user/", defaultUserDestResolver.getDestinationPrefix());
240
241 StompBrokerRelayMessageHandler messageBroker = this.appContext.getBean(StompBrokerRelayMessageHandler.class);
242 assertNotNull(messageBroker);
243 assertEquals("clientlogin", messageBroker.getClientLogin());
244 assertEquals("clientpass", messageBroker.getClientPasscode());
245 assertEquals("syslogin", messageBroker.getSystemLogin());
246 assertEquals("syspass", messageBroker.getSystemPasscode());
247 assertEquals("relayhost", messageBroker.getRelayHost());
248 assertEquals(1234, messageBroker.getRelayPort());
249 assertEquals("spring.io", messageBroker.getVirtualHost());
250 assertEquals(5000, messageBroker.getSystemHeartbeatReceiveInterval());
251 assertEquals(5000, messageBroker.getSystemHeartbeatSendInterval());
252 assertThat(messageBroker.getDestinationPrefixes(), Matchers.containsInAnyOrder("/topic","/queue"));
253
254 List<Class<? extends MessageHandler>> subscriberTypes =
255 Arrays.<Class<? extends MessageHandler>>asList(SimpAnnotationMethodMessageHandler.class,
256 UserDestinationMessageHandler.class, StompBrokerRelayMessageHandler.class);
257 testChannel("clientInboundChannel", subscriberTypes, 2);
258 testExecutor("clientInboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
259
260 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SubProtocolWebSocketHandler.class);
261 testChannel("clientOutboundChannel", subscriberTypes, 1);
262 testExecutor("clientOutboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
263
264 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(
265 StompBrokerRelayMessageHandler.class, UserDestinationMessageHandler.class);
266 testChannel("brokerChannel", subscriberTypes, 1);
267 try {
268 this.appContext.getBean("brokerChannelExecutor", ThreadPoolTaskExecutor.class);
269 fail("expected exception");
270 }
271 catch (NoSuchBeanDefinitionException ex) {
272
273 }
274
275 String name = "webSocketMessageBrokerStats";
276 WebSocketMessageBrokerStats stats = this.appContext.getBean(name, WebSocketMessageBrokerStats.class);
277 String actual = stats.toString();
278 String expected = "WebSocketSession\\[0 current WS\\(0\\)-HttpStream\\(0\\)-HttpPoll\\(0\\), " +
279 "0 total, 0 closed abnormally \\(0 connect failure, 0 send limit, 0 transport error\\)\\], " +
280 "stompSubProtocol\\[processed CONNECT\\(0\\)-CONNECTED\\(0\\)-DISCONNECT\\(0\\)\\], " +
281 "stompBrokerRelay\\[0 sessions, relayhost:1234 \\(not available\\), processed CONNECT\\(0\\)-CONNECTED\\(0\\)-DISCONNECT\\(0\\)\\], " +
282 "inboundChannel\\[pool size = \\d, active threads = \\d, queued tasks = \\d, completed tasks = \\d\\], " +
283 "outboundChannelpool size = \\d, active threads = \\d, queued tasks = \\d, completed tasks = \\d\\], " +
284 "sockJsScheduler\\[pool size = \\d, active threads = \\d, queued tasks = \\d, completed tasks = \\d\\]";
285
286 assertTrue("\nExpected: " + expected.replace("\\", "") + "\n Actual: " + actual, actual.matches(expected));
287 }
288
289 @Test
290 public void annotationMethodMessageHandler() {
291 loadBeanDefinitions("websocket-config-broker-simple.xml");
292
293 SimpAnnotationMethodMessageHandler annotationMethodMessageHandler =
294 this.appContext.getBean(SimpAnnotationMethodMessageHandler.class);
295
296 assertNotNull(annotationMethodMessageHandler);
297 MessageConverter messageConverter = annotationMethodMessageHandler.getMessageConverter();
298 assertNotNull(messageConverter);
299 assertTrue(messageConverter instanceof CompositeMessageConverter);
300
301 CompositeMessageConverter compositeMessageConverter = this.appContext.getBean(CompositeMessageConverter.class);
302 assertNotNull(compositeMessageConverter);
303
304 SimpMessagingTemplate simpMessagingTemplate = this.appContext.getBean(SimpMessagingTemplate.class);
305 assertNotNull(simpMessagingTemplate);
306 assertEquals("/personal/", simpMessagingTemplate.getUserDestinationPrefix());
307
308 List<MessageConverter> converters = compositeMessageConverter.getConverters();
309 assertThat(converters.size(), Matchers.is(3));
310 assertThat(converters.get(0), Matchers.instanceOf(StringMessageConverter.class));
311 assertThat(converters.get(1), Matchers.instanceOf(ByteArrayMessageConverter.class));
312 assertThat(converters.get(2), Matchers.instanceOf(MappingJackson2MessageConverter.class));
313
314 ContentTypeResolver resolver = ((MappingJackson2MessageConverter) converters.get(2)).getContentTypeResolver();
315 assertEquals(MimeTypeUtils.APPLICATION_JSON, ((DefaultContentTypeResolver) resolver).getDefaultMimeType());
316
317 DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(annotationMethodMessageHandler);
318 String pathSeparator = (String)new DirectFieldAccessor(handlerAccessor.getPropertyValue("pathMatcher")).getPropertyValue("pathSeparator");
319 assertEquals(".", pathSeparator);
320 }
321
322 @Test
323 public void customChannels() {
324 loadBeanDefinitions("websocket-config-broker-customchannels.xml");
325
326 List<Class<? extends MessageHandler>> subscriberTypes =
327 Arrays.<Class<? extends MessageHandler>>asList(SimpAnnotationMethodMessageHandler.class,
328 UserDestinationMessageHandler.class, SimpleBrokerMessageHandler.class);
329
330 testChannel("clientInboundChannel", subscriberTypes, 3);
331 testExecutor("clientInboundChannel", 100, 200, 600);
332
333 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SubProtocolWebSocketHandler.class);
334
335 testChannel("clientOutboundChannel", subscriberTypes, 3);
336 testExecutor("clientOutboundChannel", 101, 201, 601);
337
338 subscriberTypes = Arrays.<Class<? extends MessageHandler>>asList(SimpleBrokerMessageHandler.class,
339 UserDestinationMessageHandler.class);
340
341 testChannel("brokerChannel", subscriberTypes, 1);
342 testExecutor("brokerChannel", 102, 202, 602);
343 }
344
345
346
347 @Test
348 public void customChannelsWithDefaultExecutor() {
349 loadBeanDefinitions("websocket-config-broker-customchannels-default-executor.xml");
350
351 testExecutor("clientInboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
352 testExecutor("clientOutboundChannel", Runtime.getRuntime().availableProcessors() * 2, Integer.MAX_VALUE, 60);
353 assertFalse(this.appContext.containsBean("brokerChannelExecutor"));
354 }
355
356 @Test
357 public void customArgumentAndReturnValueTypes() {
358 loadBeanDefinitions("websocket-config-broker-custom-argument-and-return-value-types.xml");
359
360 SimpAnnotationMethodMessageHandler handler = this.appContext.getBean(SimpAnnotationMethodMessageHandler.class);
361
362 List<HandlerMethodArgumentResolver> customResolvers = handler.getCustomArgumentResolvers();
363 assertEquals(2, customResolvers.size());
364 assertTrue(handler.getArgumentResolvers().contains(customResolvers.get(0)));
365 assertTrue(handler.getArgumentResolvers().contains(customResolvers.get(1)));
366
367 List<HandlerMethodReturnValueHandler> customHandlers = handler.getCustomReturnValueHandlers();
368 assertEquals(2, customHandlers.size());
369 assertTrue(handler.getReturnValueHandlers().contains(customHandlers.get(0)));
370 assertTrue(handler.getReturnValueHandlers().contains(customHandlers.get(1)));
371 }
372
373 @Test
374 public void messageConverters() {
375 loadBeanDefinitions("websocket-config-broker-converters.xml");
376
377 CompositeMessageConverter compositeConverter = this.appContext.getBean(CompositeMessageConverter.class);
378 assertNotNull(compositeConverter);
379
380 assertEquals(4, compositeConverter.getConverters().size());
381 assertEquals(StringMessageConverter.class, compositeConverter.getConverters().iterator().next().getClass());
382 }
383
384 @Test
385 public void messageConvertersDefaultsOff() {
386 loadBeanDefinitions("websocket-config-broker-converters-defaults-off.xml");
387
388 CompositeMessageConverter compositeConverter = this.appContext.getBean(CompositeMessageConverter.class);
389 assertNotNull(compositeConverter);
390
391 assertEquals(1, compositeConverter.getConverters().size());
392 assertEquals(StringMessageConverter.class, compositeConverter.getConverters().iterator().next().getClass());
393 }
394
395
396 private void testChannel(String channelName, List<Class<? extends MessageHandler>> subscriberTypes,
397 int interceptorCount) {
398
399 AbstractSubscribableChannel channel = this.appContext.getBean(channelName, AbstractSubscribableChannel.class);
400
401 for (Class<? extends MessageHandler> subscriberType : subscriberTypes) {
402 MessageHandler subscriber = this.appContext.getBean(subscriberType);
403 assertNotNull("No subsription for " + subscriberType, subscriber);
404 assertTrue(channel.hasSubscription(subscriber));
405 }
406
407 List<ChannelInterceptor> interceptors = channel.getInterceptors();
408 assertEquals(interceptorCount, interceptors.size());
409 assertEquals(ImmutableMessageChannelInterceptor.class, interceptors.get(interceptors.size()-1).getClass());
410 }
411
412 private void testExecutor(String channelName, int corePoolSize, int maxPoolSize, int keepAliveSeconds) {
413
414 ThreadPoolTaskExecutor taskExecutor =
415 this.appContext.getBean(channelName + "Executor", ThreadPoolTaskExecutor.class);
416
417 assertEquals(corePoolSize, taskExecutor.getCorePoolSize());
418 assertEquals(maxPoolSize, taskExecutor.getMaxPoolSize());
419 assertEquals(keepAliveSeconds, taskExecutor.getKeepAliveSeconds());
420 }
421
422 private void loadBeanDefinitions(String fileName) {
423 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.appContext);
424 ClassPathResource resource = new ClassPathResource(fileName, MessageBrokerBeanDefinitionParserTests.class);
425 reader.loadBeanDefinitions(resource);
426 this.appContext.refresh();
427 }
428
429 private WebSocketHandler unwrapWebSocketHandler(WebSocketHandler handler) {
430 return (handler instanceof WebSocketHandlerDecorator) ?
431 ((WebSocketHandlerDecorator) handler).getLastHandler() : handler;
432 }
433
434 }
435
436 class CustomArgumentResolver implements HandlerMethodArgumentResolver {
437
438 @Override
439 public boolean supportsParameter(MethodParameter parameter) {
440 return false;
441 }
442
443 @Override
444 public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
445 return null;
446 }
447 }
448
449 class CustomReturnValueHandler implements HandlerMethodReturnValueHandler {
450
451 @Override
452 public boolean supportsReturnType(MethodParameter returnType) {
453 return false;
454 }
455
456 @Override
457 public void handleReturnValue(Object returnValue, MethodParameter returnType, Message<?> message) throws Exception {
458
459 }
460 }
461
462 class TestWebSocketHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
463
464 @Override
465 public WebSocketHandler decorate(WebSocketHandler handler) {
466 return new WebSocketHandlerDecorator(handler) {
467 @Override
468 public void afterConnectionEstablished(WebSocketSession session) throws Exception {
469 session.getAttributes().put("decorated", true);
470 super.afterConnectionEstablished(session);
471 }
472 };
473 }
474 }