@Bean public WebSocketHandler subProtocolWebSocketHandler() { return new SubProtocolWebSocketHandler(clientInboundChannel(), clientOutboundChannel()); }
/** * Configure one or more handlers to use depending on the sub-protocol requested by * the client in the WebSocket handshake request. * @param protocolHandlers the sub-protocol handlers to use */ public void setProtocolHandlers(List<SubProtocolHandler> protocolHandlers) { this.protocolHandlerLookup.clear(); this.protocolHandlers.clear(); for (SubProtocolHandler handler : protocolHandlers) { addProtocolHandler(handler); } }
public WebMvcStompEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler) { Assert.notNull(webSocketHandler, "WebSocketHandler is required "); Assert.notNull(transportRegistration, "WebSocketTransportRegistration is required"); this.webSocketHandler = webSocketHandler; this.subProtocolWebSocketHandler = unwrapSubProtocolWebSocketHandler(webSocketHandler); if (transportRegistration.getSendTimeLimit() != null) { this.subProtocolWebSocketHandler.setSendTimeLimit(transportRegistration.getSendTimeLimit()); } if (transportRegistration.getSendBufferSizeLimit() != null) { this.subProtocolWebSocketHandler.setSendBufferSizeLimit(transportRegistration.getSendBufferSizeLimit()); } if (transportRegistration.getTimeToFirstMessage() != null) { this.subProtocolWebSocketHandler.setTimeToFirstMessage(transportRegistration.getTimeToFirstMessage()); } this.stompHandler = new StompSubProtocolHandler(); if (transportRegistration.getMessageSizeLimit() != null) { this.stompHandler.setMessageSizeLimit(transportRegistration.getMessageSizeLimit()); } this.sockJsScheduler = defaultSockJsTaskScheduler; }
@Nullable private StompSubProtocolHandler initStompSubProtocolHandler() { if (this.webSocketHandler == null) { return null; } for (SubProtocolHandler handler : this.webSocketHandler.getProtocolHandlers()) { if (handler instanceof StompSubProtocolHandler) { return (StompSubProtocolHandler) handler; } } SubProtocolHandler defaultHandler = this.webSocketHandler.getDefaultProtocolHandler(); if (defaultHandler != null && defaultHandler instanceof StompSubProtocolHandler) { return (StompSubProtocolHandler) defaultHandler; } return null; }
/** * Decorate the given {@link WebSocketSession}, if desired. * <p>The default implementation builds a {@link ConcurrentWebSocketSessionDecorator} * with the configured {@link #getSendTimeLimit() send-time limit} and * {@link #getSendBufferSizeLimit() buffer-size limit}. * @param session the original {@code WebSocketSession} * @return the decorated {@code WebSocketSession}, or potentially the given session as-is * @since 4.3.13 */ protected WebSocketSession decorateSession(WebSocketSession session) { return new ConcurrentWebSocketSessionDecorator(session, getSendTimeLimit(), getSendBufferSizeLimit()); }
@Test(expected = IllegalStateException.class) public void noSubProtocolTwoHandlers() throws Exception { this.webSocketHandler.setProtocolHandlers(Arrays.asList(stompHandler, mqttHandler)); this.webSocketHandler.afterConnectionEstablished(session); }
@Test public void getSubProtocols() throws Exception { SubscribableChannel channel = mock(SubscribableChannel.class); SubProtocolWebSocketHandler handler = new SubProtocolWebSocketHandler(channel, channel); StompSubProtocolHandler stompHandler = new StompSubProtocolHandler(); handler.addProtocolHandler(stompHandler); TaskScheduler scheduler = mock(TaskScheduler.class); DefaultSockJsService service = new DefaultSockJsService(scheduler); WebSocketServerSockJsSession session = new WebSocketServerSockJsSession("1", service, handler, null); SockJsWebSocketHandler sockJsHandler = new SockJsWebSocketHandler(service, handler, session); assertEquals(stompHandler.getSupportedProtocols(), sockJsHandler.getSubProtocols()); }
@Test public void webSocketHandler() { ApplicationContext config = createConfig(TestChannelConfig.class, TestConfigurer.class); SubProtocolWebSocketHandler subWsHandler = config.getBean(SubProtocolWebSocketHandler.class); assertEquals(1024 * 1024, subWsHandler.getSendBufferSizeLimit()); assertEquals(25 * 1000, subWsHandler.getSendTimeLimit()); assertEquals(30 * 1000, subWsHandler.getTimeToFirstMessage()); Map<String, SubProtocolHandler> handlerMap = subWsHandler.getProtocolHandlerMap(); StompSubProtocolHandler protocolHandler = (StompSubProtocolHandler) handlerMap.get("v12.stomp"); assertEquals(128 * 1024, protocolHandler.getMessageSizeLimit()); }
public WebMvcWampEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler, JsonFactory jsonFactory) { Assert.notNull(webSocketHandler, "'webSocketHandler' is required "); Assert.notNull(transportRegistration, "'transportRegistration' is required"); Assert.notNull(jsonFactory, "'jsonFactory' is required"); this.webSocketHandler = webSocketHandler; this.subProtocolWebSocketHandler = unwrapSubProtocolWebSocketHandler( webSocketHandler); if (transportRegistration.getSendTimeLimit() != null) { this.subProtocolWebSocketHandler .setSendTimeLimit(transportRegistration.getSendTimeLimit()); } if (transportRegistration.getSendBufferSizeLimit() != null) { this.subProtocolWebSocketHandler.setSendBufferSizeLimit( transportRegistration.getSendBufferSizeLimit()); } this.wampSubProtocolHandler = new WampSubProtocolHandler(jsonFactory); this.sockJsScheduler = defaultSockJsTaskScheduler; }
String sessionId = resolveSessionId(message); if (sessionId == null) { if (logger.isErrorEnabled()) { findProtocolHandler(session).handleMessageToClient(session, message); clearSession(session, ex.getStatus()); // clear first, session may be unresponsive session.close(ex.getStatus());
/** * Handle an inbound message from a WebSocket client. */ @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { WebSocketSessionHolder holder = this.sessions.get(session.getId()); if (holder != null) { session = holder.getSession(); } SubProtocolHandler protocolHandler = findProtocolHandler(session); protocolHandler.handleMessageFromClient(session, message, this.clientInboundChannel); if (holder != null) { holder.setHasHandledMessages(); } checkSessions(); }
@Test(expected = IllegalStateException.class) public void subProtocolNoMatch() throws Exception { this.webSocketHandler.setDefaultProtocolHandler(defaultHandler); this.webSocketHandler.setProtocolHandlers(Arrays.asList(stompHandler, mqttHandler)); this.session.setAcceptedProtocol("wamp"); this.webSocketHandler.afterConnectionEstablished(session); }
@Bean public WebSocketHandler subProtocolWebSocketHandler() { SubProtocolWebSocketHandler webSocketHandler = new SubProtocolWebSocketHandler(clientInboundChannel(), clientOutboundChannel()); webSocketHandler.setDefaultProtocolHandler(stompSubProtocolHandler()); return webSocketHandler; }
@Test @SuppressWarnings("unchecked") public void checkSession() throws Exception { TestWebSocketSession session1 = new TestWebSocketSession("id1"); TestWebSocketSession session2 = new TestWebSocketSession("id2"); session1.setOpen(true); session2.setOpen(true); session1.setAcceptedProtocol("v12.stomp"); session2.setAcceptedProtocol("v12.stomp"); this.webSocketHandler.setProtocolHandlers(Arrays.asList(this.stompHandler)); this.webSocketHandler.afterConnectionEstablished(session1); this.webSocketHandler.afterConnectionEstablished(session2); DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(this.webSocketHandler); Map<String, ?> map = (Map<String, ?>) handlerAccessor.getPropertyValue("sessions"); DirectFieldAccessor session1Accessor = new DirectFieldAccessor(map.get("id1")); DirectFieldAccessor session2Accessor = new DirectFieldAccessor(map.get("id2")); long sixtyOneSecondsAgo = System.currentTimeMillis() - 61 * 1000; handlerAccessor.setPropertyValue("lastSessionCheckTime", sixtyOneSecondsAgo); session1Accessor.setPropertyValue("createTime", sixtyOneSecondsAgo); session2Accessor.setPropertyValue("createTime", sixtyOneSecondsAgo); this.webSocketHandler.start(); this.webSocketHandler.handleMessage(session1, new TextMessage("foo")); assertTrue(session1.isOpen()); assertNull(session1.getCloseStatus()); assertFalse(session2.isOpen()); assertEquals(CloseStatus.SESSION_NOT_RELIABLE, session2.getCloseStatus()); assertNotEquals("lastSessionCheckTime not updated", sixtyOneSecondsAgo, handlerAccessor.getPropertyValue("lastSessionCheckTime")); }
/** * Set the {@link SubProtocolHandler} to use when the client did not request a * sub-protocol. * @param defaultProtocolHandler the default handler */ public void setDefaultProtocolHandler(@Nullable SubProtocolHandler defaultProtocolHandler) { this.defaultProtocolHandler = defaultProtocolHandler; if (this.protocolHandlerLookup.isEmpty()) { setProtocolHandlers(Collections.singletonList(defaultProtocolHandler)); } }
@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { clearSession(session, closeStatus); }
@Test public void handlerMapping() { SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.endpointRegistry.getHandlerMapping(); assertEquals(0, hm.getUrlMap().size()); UrlPathHelper pathHelper = new UrlPathHelper(); this.endpointRegistry.setUrlPathHelper(pathHelper); this.endpointRegistry.addEndpoint("/stompOverWebSocket"); this.endpointRegistry.addEndpoint("/stompOverSockJS").withSockJS(); //SPR-12403 assertEquals(1, this.webSocketHandler.getProtocolHandlers().size()); hm = (SimpleUrlHandlerMapping) this.endpointRegistry.getHandlerMapping(); assertEquals(2, hm.getUrlMap().size()); assertNotNull(hm.getUrlMap().get("/stompOverWebSocket")); assertNotNull(hm.getUrlMap().get("/stompOverSockJS/**")); assertSame(pathHelper, hm.getUrlPathHelper()); }
@Bean public SubProtocolWebSocketHandler subProtocolWebSocketHandler() { SubProtocolWebSocketHandler subProtocolWebSocketHandler = new SubProtocolWebSocketHandler( clientInboundChannel(), clientOutboundChannel()); subProtocolWebSocketHandler.addProtocolHandler(wampSubProtocolHandler()); return subProtocolWebSocketHandler; }
assertEquals(Arrays.asList("v10.stomp", "v11.stomp", "v12.stomp"), subProtocolWsHandler.getSubProtocols()); assertEquals(25 * 1000, subProtocolWsHandler.getSendTimeLimit()); assertEquals(1024 * 1024, subProtocolWsHandler.getSendBufferSizeLimit()); assertEquals(30 * 1000, subProtocolWsHandler.getTimeToFirstMessage()); Map<String, SubProtocolHandler> handlerMap = subProtocolWsHandler.getProtocolHandlerMap(); StompSubProtocolHandler stompHandler = (StompSubProtocolHandler) handlerMap.get("v12.stomp"); assertNotNull(stompHandler);
public WebMvcStompEndpointRegistry(WebSocketHandler webSocketHandler, WebSocketTransportRegistration transportRegistration, TaskScheduler defaultSockJsTaskScheduler) { Assert.notNull(webSocketHandler, "WebSocketHandler is required "); Assert.notNull(transportRegistration, "WebSocketTransportRegistration is required"); this.webSocketHandler = webSocketHandler; this.subProtocolWebSocketHandler = unwrapSubProtocolWebSocketHandler(webSocketHandler); if (transportRegistration.getSendTimeLimit() != null) { this.subProtocolWebSocketHandler.setSendTimeLimit(transportRegistration.getSendTimeLimit()); } if (transportRegistration.getSendBufferSizeLimit() != null) { this.subProtocolWebSocketHandler.setSendBufferSizeLimit(transportRegistration.getSendBufferSizeLimit()); } this.stompHandler = new StompSubProtocolHandler(); if (transportRegistration.getMessageSizeLimit() != null) { this.stompHandler.setMessageSizeLimit(transportRegistration.getMessageSizeLimit()); } this.sockJsScheduler = defaultSockJsTaskScheduler; }