Skip to content

Commit 84089bf

Browse files
committed
Add HandlerProvider interface
HandlerProvider is now an interface that can be used to plug in WebSocket handlers with per-connection scope semantics. There are two implementations, of the interface, one simple and a second that creates handler instances through AutowireCapableBeanFactory. HandlerProvider also provides a destroy method that is used to apply a destroy callback whenever a client connection closes.
1 parent f9078c9 commit 84089bf

34 files changed

+373
-369
lines changed

spring-websocket/src/main/java/org/springframework/sockjs/AbstractSockJsSession.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.commons.logging.LogFactory;
2323
import org.springframework.util.Assert;
2424
import org.springframework.websocket.CloseStatus;
25+
import org.springframework.websocket.HandlerProvider;
2526
import org.springframework.websocket.TextMessage;
2627
import org.springframework.websocket.TextMessageHandler;
2728
import org.springframework.websocket.WebSocketHandler;
@@ -40,6 +41,8 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
4041

4142
private final String sessionId;
4243

44+
private final HandlerProvider<WebSocketHandler> handlerProvider;
45+
4346
private final TextMessageHandler handler;
4447

4548
private State state = State.NEW;
@@ -52,14 +55,17 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
5255
/**
5356
*
5457
* @param sessionId
55-
* @param handler the recipient of SockJS messages
58+
* @param handlerProvider the recipient of SockJS messages
5659
*/
57-
public AbstractSockJsSession(String sessionId, WebSocketHandler webSocketHandler) {
60+
public AbstractSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handlerProvider) {
5861
Assert.notNull(sessionId, "sessionId is required");
59-
Assert.notNull(webSocketHandler, "webSocketHandler is required");
60-
Assert.isInstanceOf(TextMessageHandler.class, webSocketHandler, "Expected a TextMessageHandler");
62+
Assert.notNull(handlerProvider, "handlerProvider is required");
6163
this.sessionId = sessionId;
64+
65+
WebSocketHandler webSocketHandler = handlerProvider.getHandler();
66+
Assert.isInstanceOf(TextMessageHandler.class, webSocketHandler, "Expected a TextMessageHandler");
6267
this.handler = (TextMessageHandler) webSocketHandler;
68+
this.handlerProvider = handlerProvider;
6369
}
6470

6571
public String getId() {
@@ -180,7 +186,12 @@ public final void close(CloseStatus status) throws Exception {
180186
}
181187
finally {
182188
this.state = State.CLOSED;
183-
this.handler.afterConnectionClosed(status, this);
189+
try {
190+
this.handler.afterConnectionClosed(status, this);
191+
}
192+
finally {
193+
this.handlerProvider.destroy(this.handler);
194+
}
184195
}
185196
}
186197
}

spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.sockjs;
1818

19+
import org.springframework.websocket.HandlerProvider;
1920
import org.springframework.websocket.WebSocketHandler;
2021
import org.springframework.websocket.WebSocketSession;
2122

@@ -28,6 +29,6 @@
2829
*/
2930
public interface SockJsSessionFactory<S extends WebSocketSession>{
3031

31-
S createSession(String sessionId, WebSocketHandler webSocketHandler);
32+
S createSession(String sessionId, HandlerProvider<WebSocketHandler> handler);
3233

3334
}

spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSockJsSession.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.sockjs.AbstractSockJsSession;
2626
import org.springframework.util.Assert;
2727
import org.springframework.websocket.CloseStatus;
28+
import org.springframework.websocket.HandlerProvider;
2829
import org.springframework.websocket.TextMessage;
2930
import org.springframework.websocket.WebSocketHandler;
3031
import org.springframework.websocket.WebSocketMessage;
@@ -45,9 +46,9 @@ public abstract class AbstractServerSockJsSession extends AbstractSockJsSession
4546

4647

4748
public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config,
48-
WebSocketHandler webSocketHandler) {
49+
HandlerProvider<WebSocketHandler> handler) {
4950

50-
super(sessionId, webSocketHandler);
51+
super(sessionId, handler);
5152
this.sockJsConfig = config;
5253
}
5354

spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractSockJsService.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.springframework.util.DigestUtils;
4040
import org.springframework.util.ObjectUtils;
4141
import org.springframework.util.StringUtils;
42+
import org.springframework.websocket.HandlerProvider;
4243
import org.springframework.websocket.WebSocketHandler;
4344

4445

@@ -218,7 +219,7 @@ public void destroy() throws Exception {
218219
* @throws Exception
219220
*/
220221
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
221-
String sockJsPath, WebSocketHandler webSocketHandler) throws Exception {
222+
String sockJsPath, HandlerProvider<WebSocketHandler> handler) throws Exception {
222223

223224
logger.debug(request.getMethod() + " [" + sockJsPath + "]");
224225

@@ -244,7 +245,7 @@ else if (sockJsPath.matches("/iframe[0-9-.a-z_]*.html")) {
244245
return;
245246
}
246247
else if (sockJsPath.equals("/websocket")) {
247-
handleRawWebSocketRequest(request, response, webSocketHandler);
248+
handleRawWebSocketRequest(request, response, handler);
248249
return;
249250
}
250251

@@ -264,18 +265,18 @@ else if (sockJsPath.equals("/websocket")) {
264265
return;
265266
}
266267

267-
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), webSocketHandler);
268+
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), handler);
268269
}
269270
finally {
270271
response.flush();
271272
}
272273
}
273274

274275
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
275-
WebSocketHandler webSocketHandler) throws Exception;
276+
HandlerProvider<WebSocketHandler> handler) throws Exception;
276277

277278
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
278-
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception;
279+
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler) throws Exception;
279280

280281

281282
protected boolean validateRequest(String serverId, String sessionId, String transport) {

spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.springframework.http.server.ServerHttpRequest;
2020
import org.springframework.http.server.ServerHttpResponse;
21+
import org.springframework.websocket.HandlerProvider;
2122
import org.springframework.websocket.WebSocketHandler;
2223

2324

@@ -30,6 +31,6 @@ public interface SockJsService {
3031

3132

3233
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, String sockJsPath,
33-
WebSocketHandler webSocketHandler) throws Exception;
34+
HandlerProvider<WebSocketHandler> handler) throws Exception;
3435

3536
}

spring-websocket/src/main/java/org/springframework/sockjs/server/TransportHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.springframework.http.server.ServerHttpRequest;
1919
import org.springframework.http.server.ServerHttpResponse;
2020
import org.springframework.sockjs.AbstractSockJsSession;
21+
import org.springframework.websocket.HandlerProvider;
2122
import org.springframework.websocket.WebSocketHandler;
2223

2324

@@ -31,6 +32,6 @@ public interface TransportHandler {
3132
TransportType getTransportType();
3233

3334
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
34-
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception;
35+
HandlerProvider<WebSocketHandler> handler, AbstractSockJsSession session) throws Exception;
3536

3637
}

spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultSockJsService.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Map;
2222
import java.util.concurrent.ConcurrentHashMap;
2323

24-
import org.springframework.beans.factory.InitializingBean;
2524
import org.springframework.http.Cookie;
2625
import org.springframework.http.HttpMethod;
2726
import org.springframework.http.HttpStatus;
@@ -43,6 +42,7 @@
4342
import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler;
4443
import org.springframework.sockjs.server.transport.XhrTransportHandler;
4544
import org.springframework.util.Assert;
45+
import org.springframework.websocket.HandlerProvider;
4646
import org.springframework.websocket.WebSocketHandler;
4747
import org.springframework.websocket.server.DefaultHandshakeHandler;
4848
import org.springframework.websocket.server.HandshakeHandler;
@@ -54,7 +54,7 @@
5454
* @author Rossen Stoyanchev
5555
* @since 4.0
5656
*/
57-
public class DefaultSockJsService extends AbstractSockJsService implements InitializingBean {
57+
public class DefaultSockJsService extends AbstractSockJsService {
5858

5959
private final Map<TransportType, TransportHandler> transportHandlers = new HashMap<TransportType, TransportHandler>();
6060

@@ -157,13 +157,13 @@ public void destroy() throws Exception {
157157

158158
@Override
159159
protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
160-
WebSocketHandler webSocketHandler) throws Exception {
160+
HandlerProvider<WebSocketHandler> handler) throws Exception {
161161

162162
if (isWebSocketEnabled()) {
163163
TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET);
164164
if (transportHandler != null) {
165165
if (transportHandler instanceof HandshakeHandler) {
166-
((HandshakeHandler) transportHandler).doHandshake(request, response, webSocketHandler);
166+
((HandshakeHandler) transportHandler).doHandshake(request, response, handler);
167167
return;
168168
}
169169
}
@@ -174,7 +174,7 @@ protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpRe
174174

175175
@Override
176176
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
177-
String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception {
177+
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler> handler) throws Exception {
178178

179179
TransportHandler transportHandler = this.transportHandlers.get(transportType);
180180

@@ -201,7 +201,7 @@ protected void handleTransportRequest(ServerHttpRequest request, ServerHttpRespo
201201
return;
202202
}
203203

204-
AbstractSockJsSession session = getSockJsSession(sessionId, webSocketHandler, transportHandler);
204+
AbstractSockJsSession session = getSockJsSession(sessionId, handler, transportHandler);
205205

206206
if (session != null) {
207207
if (transportType.setsNoCacheHeader()) {
@@ -220,10 +220,10 @@ protected void handleTransportRequest(ServerHttpRequest request, ServerHttpRespo
220220
}
221221
}
222222

223-
transportHandler.handleRequest(request, response, webSocketHandler, session);
223+
transportHandler.handleRequest(request, response, handler, session);
224224
}
225225

226-
public AbstractSockJsSession getSockJsSession(String sessionId, WebSocketHandler webSocketHandler,
226+
public AbstractSockJsSession getSockJsSession(String sessionId, HandlerProvider<WebSocketHandler> handler,
227227
TransportHandler transportHandler) {
228228

229229
AbstractSockJsSession session = this.sessions.get(sessionId);
@@ -240,7 +240,7 @@ public AbstractSockJsSession getSockJsSession(String sessionId, WebSocketHandler
240240
return session;
241241
}
242242
logger.debug("Creating new session with session id \"" + sessionId + "\"");
243-
session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, webSocketHandler);
243+
session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, handler);
244244
this.sessions.put(sessionId, session);
245245
return session;
246246
}

spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsHttpRequestHandler.java

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
import javax.servlet.http.HttpServletRequest;
2323
import javax.servlet.http.HttpServletResponse;
2424

25-
import org.springframework.beans.BeansException;
26-
import org.springframework.beans.factory.BeanFactory;
27-
import org.springframework.beans.factory.BeanFactoryAware;
2825
import org.springframework.http.server.AsyncServletServerHttpRequest;
2926
import org.springframework.http.server.ServerHttpRequest;
3027
import org.springframework.http.server.ServerHttpResponse;
@@ -36,14 +33,15 @@
3633
import org.springframework.web.util.UrlPathHelper;
3734
import org.springframework.websocket.HandlerProvider;
3835
import org.springframework.websocket.WebSocketHandler;
36+
import org.springframework.websocket.support.SimpleHandlerProvider;
3937

4038

4139
/**
4240
*
4341
* @author Rossen Stoyanchev
4442
* @since 4.0
4543
*/
46-
public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactoryAware {
44+
public class SockJsHttpRequestHandler implements HttpRequestHandler {
4745

4846
private final String prefix;
4947

@@ -61,15 +59,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
6159
* that begins with the specified prefix will be handled by this service. In a
6260
* Servlet container this is the path within the current servlet mapping.
6361
*/
64-
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler webSocketHandler) {
62+
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler handler) {
6563

6664
Assert.hasText(prefix, "prefix is required");
6765
Assert.notNull(sockJsService, "sockJsService is required");
68-
Assert.notNull(webSocketHandler, "webSocketHandler is required");
66+
Assert.notNull(handler, "webSocketHandler is required");
6967

7068
this.prefix = prefix;
7169
this.sockJsService = sockJsService;
72-
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandler);
70+
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler>(handler);
7371
}
7472

7573
/**
@@ -80,15 +78,15 @@ public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebS
8078
* Servlet container this is the path within the current servlet mapping.
8179
*/
8280
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService,
83-
Class<? extends WebSocketHandler> webSocketHandlerClass) {
81+
HandlerProvider<WebSocketHandler> handlerProvider) {
8482

8583
Assert.hasText(prefix, "prefix is required");
8684
Assert.notNull(sockJsService, "sockJsService is required");
87-
Assert.notNull(webSocketHandlerClass, "webSocketHandlerClass is required");
85+
Assert.notNull(handlerProvider, "handlerProvider is required");
8886

8987
this.prefix = prefix;
9088
this.sockJsService = sockJsService;
91-
this.handlerProvider = new HandlerProvider<WebSocketHandler>(webSocketHandlerClass);
89+
this.handlerProvider = handlerProvider;
9290
}
9391

9492
public String getPrefix() {
@@ -99,11 +97,6 @@ public String getPattern() {
9997
return this.prefix + "/**";
10098
}
10199

102-
@Override
103-
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
104-
this.handlerProvider.setBeanFactory(beanFactory);
105-
}
106-
107100
@Override
108101
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
109102
throws ServletException, IOException {
@@ -119,8 +112,7 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon
119112
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
120113

121114
try {
122-
WebSocketHandler webSocketHandler = this.handlerProvider.getHandler();
123-
this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, webSocketHandler);
115+
this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, this.handlerProvider);
124116
}
125117
catch (Exception ex) {
126118
// TODO

spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpReceivingTransportHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.http.server.ServerHttpResponse;
2828
import org.springframework.sockjs.AbstractSockJsSession;
2929
import org.springframework.sockjs.server.TransportHandler;
30+
import org.springframework.websocket.HandlerProvider;
3031
import org.springframework.websocket.WebSocketHandler;
3132

3233
import com.fasterxml.jackson.databind.JsonMappingException;
@@ -53,7 +54,7 @@ public ObjectMapper getObjectMapper() {
5354

5455
@Override
5556
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
56-
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
57+
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session) throws Exception {
5758

5859
if (session == null) {
5960
response.setStatusCode(HttpStatus.NOT_FOUND);

spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpSendingTransportHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.sockjs.server.SockJsConfiguration;
2929
import org.springframework.sockjs.server.SockJsFrame;
3030
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
31+
import org.springframework.websocket.HandlerProvider;
3132
import org.springframework.websocket.WebSocketHandler;
3233

3334
/**
@@ -55,7 +56,7 @@ public SockJsConfiguration getSockJsConfig() {
5556

5657
@Override
5758
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
58-
WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
59+
HandlerProvider<WebSocketHandler> webSocketHandler, AbstractSockJsSession session) throws Exception {
5960

6061
// Set content type before writing
6162
response.getHeaders().setContentType(getContentType());

spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpServerSockJsSession.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.sockjs.server.TransportHandler;
3030
import org.springframework.util.Assert;
3131
import org.springframework.websocket.CloseStatus;
32+
import org.springframework.websocket.HandlerProvider;
3233
import org.springframework.websocket.WebSocketHandler;
3334

3435
/**
@@ -49,9 +50,9 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
4950

5051

5152
public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
52-
WebSocketHandler webSocketHandler) {
53+
HandlerProvider<WebSocketHandler> handler) {
5354

54-
super(sessionId, sockJsConfig, webSocketHandler);
55+
super(sessionId, sockJsConfig, handler);
5556
}
5657

5758
public void setFrameFormat(FrameFormat frameFormat) {

0 commit comments

Comments
 (0)