Remove HandlerProvider

This commit is contained in:
Rossen Stoyanchev 2013-04-26 21:59:04 -04:00
parent 861ab900ae
commit 0c1b329949
40 changed files with 280 additions and 367 deletions

View File

@ -23,7 +23,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.TextMessage; import org.springframework.websocket.TextMessage;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -53,15 +52,14 @@ public abstract class AbstractSockJsSession implements WebSocketSession {
/** /**
*
* @param sessionId * @param sessionId
* @param handlerProvider the recipient of SockJS messages * @param webSocketHandler the recipient of SockJS messages
*/ */
public AbstractSockJsSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handlerProvider) { public AbstractSockJsSession(String sessionId, WebSocketHandler<?> webSocketHandler) {
Assert.notNull(sessionId, "sessionId is required"); Assert.notNull(sessionId, "sessionId is required");
Assert.notNull(handlerProvider, "handlerProvider is required"); Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.sessionId = sessionId; this.sessionId = sessionId;
this.handler = new WebSocketHandlerInvoker(handlerProvider).setLogger(logger); this.handler = new WebSocketHandlerInvoker(webSocketHandler).setLogger(logger);
} }
public String getId() { public String getId() {

View File

@ -16,7 +16,6 @@
package org.springframework.sockjs; package org.springframework.sockjs;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -32,9 +31,9 @@ public interface SockJsSessionFactory<S extends WebSocketSession>{
/** /**
* Create a new SockJS session. * Create a new SockJS session.
* @param sessionId the ID of the session * @param sessionId the ID of the session
* @param handler the underlying {@link WebSocketHandler} * @param webSocketHandler the underlying {@link WebSocketHandler}
* @return a new non-null session * @return a new non-null session
*/ */
S createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler); S createSession(String sessionId, WebSocketHandler<?> webSocketHandler);
} }

View File

@ -25,7 +25,6 @@ import java.util.concurrent.ScheduledFuture;
import org.springframework.sockjs.AbstractSockJsSession; import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.TextMessage; import org.springframework.websocket.TextMessage;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketMessage; import org.springframework.websocket.WebSocketMessage;
@ -44,9 +43,7 @@ public abstract class AbstractServerSockJsSession extends AbstractSockJsSession
private ScheduledFuture<?> heartbeatTask; private ScheduledFuture<?> heartbeatTask;
public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config, public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler<?> handler) {
HandlerProvider<WebSocketHandler<?>> handler) {
super(sessionId, handler); super(sessionId, handler);
this.sockJsConfig = config; this.sockJsConfig = config;
} }

View File

@ -36,7 +36,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -200,8 +199,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
* @throws Exception * @throws Exception
*/ */
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
String sockJsPath, HandlerProvider<WebSocketHandler<?>> handler) String sockJsPath, WebSocketHandler<?> webSocketHandler) throws IOException, TransportErrorException {
throws IOException, TransportErrorException {
logger.debug(request.getMethod() + " [" + sockJsPath + "]"); logger.debug(request.getMethod() + " [" + sockJsPath + "]");
@ -227,7 +225,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
return; return;
} }
else if (sockJsPath.equals("/websocket")) { else if (sockJsPath.equals("/websocket")) {
handleRawWebSocketRequest(request, response, handler); handleRawWebSocketRequest(request, response, webSocketHandler);
return; return;
} }
@ -247,18 +245,18 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
return; return;
} }
handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), handler); handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), webSocketHandler);
} }
finally { finally {
response.flush(); response.flush();
} }
} }
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response, protected abstract void handleRawWebSocketRequest(ServerHttpRequest request,
HandlerProvider<WebSocketHandler<?>> handler) throws IOException; ServerHttpResponse response, WebSocketHandler<?> webSocketHandler) throws IOException;
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response, protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler<?>> handler) String sessionId, TransportType transportType, WebSocketHandler<?> webSocketHandler)
throws IOException, TransportErrorException; throws IOException, TransportErrorException;

View File

@ -17,7 +17,6 @@
package org.springframework.sockjs.server; package org.springframework.sockjs.server;
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev

View File

@ -20,7 +20,6 @@ import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -29,7 +28,8 @@ import org.springframework.websocket.WebSocketHandler;
*/ */
public interface SockJsService { public interface SockJsService {
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, String sockJsPath,
HandlerProvider<WebSocketHandler<?>> handler) throws IOException, TransportErrorException; void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
String sockJsPath, WebSocketHandler<?> webSocketHandler) throws IOException, TransportErrorException;
} }

View File

@ -19,7 +19,6 @@ package org.springframework.sockjs.server;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.sockjs.AbstractSockJsSession; import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -31,6 +30,6 @@ public interface TransportHandler {
TransportType getTransportType(); TransportType getTransportType();
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> handler, AbstractSockJsSession session) throws TransportErrorException; WebSocketHandler<?> handler, AbstractSockJsSession session) throws TransportErrorException;
} }

View File

@ -51,7 +51,6 @@ import org.springframework.sockjs.server.transport.XhrPollingTransportHandler;
import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler; import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler;
import org.springframework.sockjs.server.transport.XhrTransportHandler; import org.springframework.sockjs.server.transport.XhrTransportHandler;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.server.DefaultHandshakeHandler; import org.springframework.websocket.server.DefaultHandshakeHandler;
import org.springframework.websocket.server.HandshakeHandler; import org.springframework.websocket.server.HandshakeHandler;
@ -143,13 +142,13 @@ public class DefaultSockJsService extends AbstractSockJsService {
@Override @Override
protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response, protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> handler) throws IOException { WebSocketHandler<?> webSocketHandler) throws IOException {
if (isWebSocketEnabled()) { if (isWebSocketEnabled()) {
TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET); TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET);
if (transportHandler != null) { if (transportHandler != null) {
if (transportHandler instanceof HandshakeHandler) { if (transportHandler instanceof HandshakeHandler) {
((HandshakeHandler) transportHandler).doHandshake(request, response, handler); ((HandshakeHandler) transportHandler).doHandshake(request, response, webSocketHandler);
return; return;
} }
} }
@ -160,7 +159,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
@Override @Override
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response, protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
String sessionId, TransportType transportType, HandlerProvider<WebSocketHandler<?>> handler) String sessionId, TransportType transportType, WebSocketHandler<?> webSocketHandler)
throws IOException, TransportErrorException { throws IOException, TransportErrorException {
TransportHandler transportHandler = this.transportHandlers.get(transportType); TransportHandler transportHandler = this.transportHandlers.get(transportType);
@ -188,7 +187,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
return; return;
} }
AbstractSockJsSession session = getSockJsSession(sessionId, handler, transportHandler); AbstractSockJsSession session = getSockJsSession(sessionId, webSocketHandler, transportHandler);
if (session != null) { if (session != null) {
if (transportType.setsNoCacheHeader()) { if (transportType.setsNoCacheHeader()) {
@ -207,11 +206,11 @@ public class DefaultSockJsService extends AbstractSockJsService {
} }
} }
transportHandler.handleRequest(request, response, handler, session); transportHandler.handleRequest(request, response, webSocketHandler, session);
} }
public AbstractSockJsSession getSockJsSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler, public AbstractSockJsSession getSockJsSession(String sessionId,
TransportHandler transportHandler) { WebSocketHandler<?> webSocketHandler, TransportHandler transportHandler) {
AbstractSockJsSession session = this.sessions.get(sessionId); AbstractSockJsSession session = this.sessions.get(sessionId);
if (session != null) { if (session != null) {
@ -230,7 +229,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
scheduleSessionTask(); scheduleSessionTask();
} }
logger.debug("Creating new session with session id \"" + sessionId + "\""); logger.debug("Creating new session with session id \"" + sessionId + "\"");
session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, handler); session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, webSocketHandler);
this.sessions.put(sessionId, session); this.sessions.put(sessionId, session);
return session; return session;
} }

View File

@ -31,9 +31,7 @@ import org.springframework.util.Assert;
import org.springframework.web.HttpRequestHandler; import org.springframework.web.HttpRequestHandler;
import org.springframework.web.util.NestedServletException; import org.springframework.web.util.NestedServletException;
import org.springframework.web.util.UrlPathHelper; import org.springframework.web.util.UrlPathHelper;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@ -45,7 +43,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
private final SockJsService sockJsService; private final SockJsService sockJsService;
private final HandlerProvider<WebSocketHandler<?>> handlerProvider; private final WebSocketHandler<?> webSocketHandler;
private final UrlPathHelper urlPathHelper = new UrlPathHelper(); private final UrlPathHelper urlPathHelper = new UrlPathHelper();
@ -57,37 +55,17 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
* that begins with the specified prefix will be handled by this service. In a * that begins with the specified prefix will be handled by this service. In a
* Servlet container this is the path within the current servlet mapping. * Servlet container this is the path within the current servlet mapping.
*/ */
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler handler) { public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler webSocketHandler) {
Assert.hasText(prefix, "prefix is required"); Assert.hasText(prefix, "prefix is required");
Assert.notNull(sockJsService, "sockJsService is required"); Assert.notNull(sockJsService, "sockJsService is required");
Assert.notNull(handler, "webSocketHandler is required"); Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.prefix = prefix; this.prefix = prefix;
this.sockJsService = sockJsService; this.sockJsService = sockJsService;
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler<?>>(handler); this.webSocketHandler = webSocketHandler;
} }
/**
* Class constructor with {@link SockJsHandler} type (per request) ...
*
* @param prefix the path prefix for the SockJS service. All requests with a path
* that begins with the specified prefix will be handled by this service. In a
* Servlet container this is the path within the current servlet mapping.
*/
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService,
HandlerProvider<WebSocketHandler<?>> handlerProvider) {
Assert.hasText(prefix, "prefix is required");
Assert.notNull(sockJsService, "sockJsService is required");
Assert.notNull(handlerProvider, "handlerProvider is required");
this.prefix = prefix;
this.sockJsService = sockJsService;
this.handlerProvider = handlerProvider;
}
public String getPrefix() { public String getPrefix() {
return this.prefix; return this.prefix;
} }
@ -111,7 +89,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response); ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
try { try {
this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, this.handlerProvider); this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, this.webSocketHandler);
} }
catch (Exception ex) { catch (Exception ex) {
// TODO // TODO

View File

@ -29,7 +29,6 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.sockjs.AbstractSockJsSession; import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.sockjs.server.TransportErrorException; import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.sockjs.server.TransportHandler; import org.springframework.sockjs.server.TransportHandler;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
@ -55,7 +54,7 @@ public abstract class AbstractHttpReceivingTransportHandler implements Transport
@Override @Override
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> webSocketHandler, AbstractSockJsSession session) WebSocketHandler<?> webSocketHandler, AbstractSockJsSession session)
throws TransportErrorException { throws TransportErrorException {
if (session == null) { if (session == null) {

View File

@ -28,9 +28,8 @@ import org.springframework.sockjs.SockJsSessionFactory;
import org.springframework.sockjs.server.ConfigurableTransportHandler; import org.springframework.sockjs.server.ConfigurableTransportHandler;
import org.springframework.sockjs.server.SockJsConfiguration; import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame; import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.websocket.HandlerProvider; import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -58,7 +57,7 @@ public abstract class AbstractHttpSendingTransportHandler
@Override @Override
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> webSocketHandler, AbstractSockJsSession session) WebSocketHandler<?> webSocketHandler, AbstractSockJsSession session)
throws TransportErrorException { throws TransportErrorException {
// Set content type before writing // Set content type before writing

View File

@ -26,11 +26,10 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.sockjs.server.AbstractServerSockJsSession; import org.springframework.sockjs.server.AbstractServerSockJsSession;
import org.springframework.sockjs.server.SockJsConfiguration; import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame; import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -50,10 +49,8 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
private ServerHttpResponse response; private ServerHttpResponse response;
public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler<?> handler) {
HandlerProvider<WebSocketHandler<?>> handler) { super(sessionId, config, handler);
super(sessionId, sockJsConfig, handler);
} }
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response, public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,

View File

@ -25,7 +25,6 @@ import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportType; import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -47,7 +46,7 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
} }
@Override @Override
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) { public StreamingServerSockJsSession createSession(String sessionId, WebSocketHandler<?> handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration"); Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) { return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {
@Override @Override

View File

@ -30,7 +30,6 @@ import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.util.JavaScriptUtils; import org.springframework.web.util.JavaScriptUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -81,7 +80,7 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
} }
@Override @Override
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) { public StreamingServerSockJsSession createSession(String sessionId, WebSocketHandler<?> handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration"); Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) { return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {

View File

@ -29,7 +29,6 @@ import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.util.JavaScriptUtils; import org.springframework.web.util.JavaScriptUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -51,7 +50,7 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
} }
@Override @Override
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) { public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler<?> handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration"); Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler); return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
} }

View File

@ -19,16 +19,13 @@ import java.io.IOException;
import org.springframework.sockjs.server.SockJsConfiguration; import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame; import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession { public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession {
public PollingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, public PollingServerSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler<?> handler) {
HandlerProvider<WebSocketHandler<?>> handler) { super(sessionId, config, handler);
super(sessionId, sockJsConfig, handler);
} }
@Override @Override

View File

@ -25,7 +25,6 @@ import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.TextMessage; import org.springframework.websocket.TextMessage;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -45,7 +44,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
private final SockJsConfiguration sockJsConfig; private final SockJsConfiguration sockJsConfig;
private final HandlerProvider<WebSocketHandler<?>> handlerProvider; private final WebSocketHandler<?> webSocketHandler;
private WebSocketServerSockJsSession sockJsSession; private WebSocketServerSockJsSession sockJsSession;
@ -55,11 +54,11 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
public SockJsWebSocketHandler(SockJsConfiguration config, HandlerProvider<WebSocketHandler<?>> handlerProvider) { public SockJsWebSocketHandler(SockJsConfiguration config, WebSocketHandler<?> webSocketHandler) {
Assert.notNull(config, "sockJsConfig is required"); Assert.notNull(config, "sockJsConfig is required");
Assert.notNull(handlerProvider, "handlerProvider is required"); Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.sockJsConfig = config; this.sockJsConfig = config;
this.handlerProvider = handlerProvider; this.webSocketHandler = webSocketHandler;
} }
protected SockJsConfiguration getSockJsConfig() { protected SockJsConfiguration getSockJsConfig() {
@ -103,7 +102,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
public WebSocketServerSockJsSession(String sessionId, SockJsConfiguration config) { public WebSocketServerSockJsSession(String sessionId, SockJsConfiguration config) {
super(sessionId, config, SockJsWebSocketHandler.this.handlerProvider); super(sessionId, config, SockJsWebSocketHandler.this.webSocketHandler);
} }
public void initWebSocketSession(WebSocketSession wsSession) { public void initWebSocketSession(WebSocketSession wsSession) {

View File

@ -24,7 +24,6 @@ import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame; import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportErrorException; import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSession { public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSession {
@ -32,10 +31,8 @@ public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSessio
private int byteCount; private int byteCount;
public StreamingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, public StreamingServerSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler<?> handler) {
HandlerProvider<WebSocketHandler<?>> handler) { super(sessionId, config, handler);
super(sessionId, sockJsConfig, handler);
} }

View File

@ -27,10 +27,8 @@ import org.springframework.sockjs.server.TransportErrorException;
import org.springframework.sockjs.server.TransportHandler; import org.springframework.sockjs.server.TransportHandler;
import org.springframework.sockjs.server.TransportType; import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.server.HandshakeHandler; import org.springframework.websocket.server.HandshakeHandler;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
@ -65,11 +63,11 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
@Override @Override
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> handler, AbstractSockJsSession session) throws TransportErrorException { WebSocketHandler<?> webSocketHandler, AbstractSockJsSession session) throws TransportErrorException {
try { try {
WebSocketHandler<?> sockJsWrapper = new SockJsWebSocketHandler(this.sockJsConfig, handler); WebSocketHandler<?> sockJsWrapper = new SockJsWebSocketHandler(this.sockJsConfig, webSocketHandler);
this.handshakeHandler.doHandshake(request, response, new SimpleHandlerProvider<WebSocketHandler<?>>(sockJsWrapper)); this.handshakeHandler.doHandshake(request, response, sockJsWrapper);
} }
catch (Throwable t) { catch (Throwable t) {
throw new TransportErrorException("Failed to start handshake request", t, session.getId()); throw new TransportErrorException("Failed to start handshake request", t, session.getId());
@ -79,8 +77,8 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
// HandshakeHandler methods // HandshakeHandler methods
@Override @Override
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler<?> handler)
HandlerProvider<WebSocketHandler<?>> handler) throws IOException { throws IOException {
return this.handshakeHandler.doHandshake(request, response, handler); return this.handshakeHandler.doHandshake(request, response, handler);
} }

View File

@ -23,7 +23,6 @@ import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportType; import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
@ -51,7 +50,7 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
return new DefaultFrameFormat("%s\n"); return new DefaultFrameFormat("%s\n");
} }
public PollingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) { public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler<?> handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration"); Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler); return new PollingServerSockJsSession(sessionId, getSockJsConfig(), handler);
} }

View File

@ -24,7 +24,6 @@ import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat; import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportType; import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
@ -48,7 +47,7 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
} }
@Override @Override
public StreamingServerSockJsSession createSession(String sessionId, HandlerProvider<WebSocketHandler<?>> handler) { public StreamingServerSockJsSession createSession(String sessionId, WebSocketHandler<?> handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration"); Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) { return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), handler) {

View File

@ -1,48 +0,0 @@
/*
* Copyright 2002-2013 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.websocket;
/**
* A strategy for obtaining a handler instance that is scoped to external lifecycle events
* such as the opening and closing of a WebSocket connection.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public interface HandlerProvider<T> {
/**
* Whether the provided handler is a shared instance or not.
*/
boolean isSingleton();
/**
* The type of handler provided.
*/
Class<?> getHandlerType();
/**
* Obtain the handler instance, either shared or created every time.
*/
T getHandler();
/**
* Callback to destroy a previously created handler instance if it is not shared.
*/
void destroy(T handler);
}

View File

@ -23,7 +23,6 @@ import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.BinaryMessage; import org.springframework.websocket.BinaryMessage;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.TextMessage; import org.springframework.websocket.TextMessage;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketMessage; import org.springframework.websocket.WebSocketMessage;
@ -39,43 +38,43 @@ public class JettyWebSocketListenerAdapter implements WebSocketListener {
private static Log logger = LogFactory.getLog(JettyWebSocketListenerAdapter.class); private static Log logger = LogFactory.getLog(JettyWebSocketListenerAdapter.class);
private final WebSocketHandler<WebSocketMessage<?>> handler; private final WebSocketHandler<WebSocketMessage<?>> webSocketHandler;
private WebSocketSession wsSession; private WebSocketSession wsSession;
public JettyWebSocketListenerAdapter(HandlerProvider<WebSocketHandler<?>> provider) { public JettyWebSocketListenerAdapter(WebSocketHandler<?> webSocketHandler) {
Assert.notNull(provider, "provider is required"); Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.handler = new WebSocketHandlerInvoker(provider).setLogger(logger); this.webSocketHandler = new WebSocketHandlerInvoker(webSocketHandler).setLogger(logger);
} }
@Override @Override
public void onWebSocketConnect(Session session) { public void onWebSocketConnect(Session session) {
this.wsSession = new JettyWebSocketSessionAdapter(session); this.wsSession = new JettyWebSocketSessionAdapter(session);
this.handler.afterConnectionEstablished(this.wsSession); this.webSocketHandler.afterConnectionEstablished(this.wsSession);
} }
@Override @Override
public void onWebSocketClose(int statusCode, String reason) { public void onWebSocketClose(int statusCode, String reason) {
CloseStatus closeStatus = new CloseStatus(statusCode, reason); CloseStatus closeStatus = new CloseStatus(statusCode, reason);
this.handler.afterConnectionClosed(this.wsSession, closeStatus); this.webSocketHandler.afterConnectionClosed(this.wsSession, closeStatus);
} }
@Override @Override
public void onWebSocketText(String payload) { public void onWebSocketText(String payload) {
TextMessage message = new TextMessage(payload); TextMessage message = new TextMessage(payload);
this.handler.handleMessage(this.wsSession, message); this.webSocketHandler.handleMessage(this.wsSession, message);
} }
@Override @Override
public void onWebSocketBinary(byte[] payload, int offset, int len) { public void onWebSocketBinary(byte[] payload, int offset, int len) {
BinaryMessage message = new BinaryMessage(payload, offset, len); BinaryMessage message = new BinaryMessage(payload, offset, len);
this.handler.handleMessage(this.wsSession, message); this.webSocketHandler.handleMessage(this.wsSession, message);
} }
@Override @Override
public void onWebSocketError(Throwable cause) { public void onWebSocketError(Throwable cause) {
this.handler.handleTransportError(this.wsSession, cause); this.webSocketHandler.handleTransportError(this.wsSession, cause);
} }
} }

View File

@ -28,11 +28,9 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.BinaryMessage; import org.springframework.websocket.BinaryMessage;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.PartialMessageHandler; import org.springframework.websocket.PartialMessageHandler;
import org.springframework.websocket.TextMessage; import org.springframework.websocket.TextMessage;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketMessage;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -46,7 +44,7 @@ public class StandardEndpointAdapter extends Endpoint {
private static Log logger = LogFactory.getLog(StandardEndpointAdapter.class); private static Log logger = LogFactory.getLog(StandardEndpointAdapter.class);
private final WebSocketHandler<WebSocketMessage<?>> handler; private final WebSocketHandlerInvoker handler;
private final Class<?> handlerClass; private final Class<?> handlerClass;
@ -54,10 +52,10 @@ public class StandardEndpointAdapter extends Endpoint {
public StandardEndpointAdapter(HandlerProvider<WebSocketHandler<?>> provider) { public StandardEndpointAdapter(WebSocketHandler<?> webSocketHandler) {
Assert.notNull(provider, "provider is required"); Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.handler = new WebSocketHandlerInvoker(provider).setLogger(logger); this.handler = new WebSocketHandlerInvoker(webSocketHandler).setLogger(logger);
this.handlerClass= provider.getHandlerType(); this.handlerClass= webSocketHandler.getClass();
} }
@ -71,6 +69,8 @@ public class StandardEndpointAdapter extends Endpoint {
} }
}); });
// TODO: per-connection proxy
if (!PartialMessageHandler.class.isAssignableFrom(this.handlerClass)) { if (!PartialMessageHandler.class.isAssignableFrom(this.handlerClass)) {
session.addMessageHandler(new MessageHandler.Whole<ByteBuffer>() { session.addMessageHandler(new MessageHandler.Whole<ByteBuffer>() {
@Override @Override

View File

@ -23,7 +23,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus; import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketMessage; import org.springframework.websocket.WebSocketMessage;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -41,18 +40,18 @@ public class WebSocketHandlerInvoker implements WebSocketHandler<WebSocketMessag
private Log logger = LogFactory.getLog(WebSocketHandlerInvoker.class); private Log logger = LogFactory.getLog(WebSocketHandlerInvoker.class);
private final HandlerProvider<WebSocketHandler<?>> handlerProvider; private final WebSocketHandler<?> handler;
private final Class<?> supportedMessageType; private final Class<?> supportedMessageType;
private WebSocketHandler<?> handler;
private final AtomicInteger sessionCount = new AtomicInteger(0); private final AtomicInteger sessionCount = new AtomicInteger(0);
public WebSocketHandlerInvoker(HandlerProvider<WebSocketHandler<?>> provider) { public WebSocketHandlerInvoker(WebSocketHandler<?> webSocketHandler) {
this.handlerProvider = provider; Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.supportedMessageType = GenericTypeResolver.resolveTypeArgument(provider.getHandlerType(), WebSocketHandler.class); this.handler = webSocketHandler;
Class<?> handlerType = webSocketHandler.getClass();
this.supportedMessageType = GenericTypeResolver.resolveTypeArgument(handlerType, WebSocketHandler.class);
} }
public WebSocketHandlerInvoker setLogger(Log logger) { public WebSocketHandlerInvoker setLogger(Log logger) {
@ -68,7 +67,6 @@ public class WebSocketHandlerInvoker implements WebSocketHandler<WebSocketMessag
try { try {
Assert.isTrue(this.sessionCount.compareAndSet(0, 1), "Unexpected new session"); Assert.isTrue(this.sessionCount.compareAndSet(0, 1), "Unexpected new session");
this.handler = this.handlerProvider.getHandler();
this.handler.afterConnectionEstablished(session); this.handler.afterConnectionEstablished(session);
} }
catch (Throwable ex) { catch (Throwable ex) {
@ -86,28 +84,14 @@ public class WebSocketHandlerInvoker implements WebSocketHandler<WebSocketMessag
} }
if (session.isOpen()) { if (session.isOpen()) {
try { try {
session.close(CloseStatus.SERVER_ERROR); session.close((status != null) ? status : CloseStatus.SERVER_ERROR);
} }
catch (Throwable t) { catch (Throwable t) {
destroyHandler(); // ignore
} }
} }
} }
private void destroyHandler() {
try {
if (this.handler != null) {
this.handlerProvider.destroy(this.handler);
}
}
catch (Throwable t) {
logger.warn("Error while destroying handler", t);
}
finally {
this.handler = null;
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) { public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
@ -150,9 +134,6 @@ public class WebSocketHandlerInvoker implements WebSocketHandler<WebSocketMessag
catch (Throwable ex) { catch (Throwable ex) {
logger.error("Unhandled error for " + this, ex); logger.error("Unhandled error for " + this, ex);
} }
finally {
this.handlerProvider.destroy(this.handler);
}
} }
} }

View File

@ -18,7 +18,6 @@ package org.springframework.websocket.client;
import java.net.URI; import java.net.URI;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
@ -35,13 +34,11 @@ import org.springframework.websocket.WebSocketSession;
*/ */
public interface WebSocketClient { public interface WebSocketClient {
WebSocketSession doHandshake(WebSocketHandler handler,
WebSocketSession doHandshake(WebSocketHandler webSocketHandler,
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException; String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler, WebSocketSession doHandshake(WebSocketHandler<?> webSocketHandler, HttpHeaders headers, URI uri)
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;
WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler, HttpHeaders headers, URI uri)
throws WebSocketConnectFailureException; throws WebSocketConnectFailureException;
} }

View File

@ -21,10 +21,8 @@ import java.util.List;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@ -34,7 +32,7 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
private final WebSocketClient client; private final WebSocketClient client;
private final HandlerProvider<WebSocketHandler<?>> handlerProvider; private final WebSocketHandler<?> webSocketHandler;
private WebSocketSession webSocketSession; private WebSocketSession webSocketSession;
@ -46,18 +44,9 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
super(uriTemplate, uriVariables); super(uriTemplate, uriVariables);
this.client = webSocketClient; this.client = webSocketClient;
this.handlerProvider = new SimpleHandlerProvider<WebSocketHandler<?>>(webSocketHandler); this.webSocketHandler = webSocketHandler;
} }
public WebSocketConnectionManager(WebSocketClient webSocketClient,
HandlerProvider<WebSocketHandler<?>> handlerProvider, String uriTemplate, Object... uriVariables) {
super(uriTemplate, uriVariables);
this.client = webSocketClient;
this.handlerProvider = handlerProvider;
}
public void setSubProtocols(List<String> subProtocols) { public void setSubProtocols(List<String> subProtocols) {
this.subProtocols.clear(); this.subProtocols.clear();
if (!CollectionUtils.isEmpty(subProtocols)) { if (!CollectionUtils.isEmpty(subProtocols)) {
@ -73,7 +62,7 @@ public class WebSocketConnectionManager extends AbstractWebSocketConnectionManag
protected void openConnection() throws Exception { protected void openConnection() throws Exception {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setSecWebSocketProtocol(this.subProtocols); headers.setSecWebSocketProtocol(this.subProtocols);
this.webSocketSession = this.client.doHandshake(this.handlerProvider, headers, getUri()); this.webSocketSession = this.client.doHandshake(this.webSocketHandler, headers, getUri());
} }
@Override @Override

View File

@ -21,9 +21,7 @@ import javax.websocket.Session;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.support.BeanCreatingHandlerProvider; import org.springframework.websocket.support.BeanCreatingHandlerProvider;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@ -32,30 +30,34 @@ import org.springframework.websocket.support.SimpleHandlerProvider;
public class AnnotatedEndpointConnectionManager extends EndpointConnectionManagerSupport public class AnnotatedEndpointConnectionManager extends EndpointConnectionManagerSupport
implements BeanFactoryAware { implements BeanFactoryAware {
private final HandlerProvider<Object> handlerProvider; private final BeanCreatingHandlerProvider<Object> endpointProvider;
private final Object endpoint;
public AnnotatedEndpointConnectionManager(Object endpointBean, String uriTemplate, Object... uriVariables) { public AnnotatedEndpointConnectionManager(Object endpoint, String uriTemplate, Object... uriVariables) {
super(uriTemplate, uriVariables); super(uriTemplate, uriVariables);
this.handlerProvider = new SimpleHandlerProvider<Object>(endpointBean); this.endpointProvider = null;
this.endpoint = endpoint;
} }
public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) { public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) {
super(uriTemplate, uriVariables); super(uriTemplate, uriVariables);
this.handlerProvider = new BeanCreatingHandlerProvider<Object>(endpointClass); this.endpointProvider = new BeanCreatingHandlerProvider<Object>(endpointClass);
this.endpoint = null;
} }
@Override @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.handlerProvider instanceof BeanFactoryAware) { if (this.endpointProvider != null) {
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory); this.endpointProvider.setBeanFactory(beanFactory);
} }
} }
@Override @Override
protected void openConnection() throws Exception { protected void openConnection() throws Exception {
Object endpoint = this.handlerProvider.getHandler(); Object endpoint = (this.endpoint != null) ? this.endpoint : this.endpointProvider.getHandler();
Session session = getWebSocketContainer().connectToServer(endpoint, getUri()); Session session = getWebSocketContainer().connectToServer(endpoint, getUri());
updateSession(session); updateSession(session);
} }

View File

@ -31,9 +31,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.support.BeanCreatingHandlerProvider; import org.springframework.websocket.support.BeanCreatingHandlerProvider;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
@ -43,19 +41,23 @@ public class EndpointConnectionManager extends EndpointConnectionManagerSupport
private final ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create(); private final ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create();
private final HandlerProvider<Endpoint> handlerProvider; private final BeanCreatingHandlerProvider<Endpoint> endpointProvider;
private final Endpoint endpoint;
public EndpointConnectionManager(Endpoint endpointBean, String uriTemplate, Object... uriVariables) { public EndpointConnectionManager(Endpoint endpoint, String uriTemplate, Object... uriVariables) {
super(uriTemplate, uriVariables); super(uriTemplate, uriVariables);
Assert.notNull(endpointBean, "endpointBean is required"); Assert.notNull(endpoint, "endpoint is required");
this.handlerProvider = new SimpleHandlerProvider<Endpoint>(endpointBean); this.endpointProvider = null;
this.endpoint = endpoint;
} }
public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVars) { public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVars) {
super(uriTemplate, uriVars); super(uriTemplate, uriVars);
Assert.notNull(endpointClass, "endpointClass is required"); Assert.notNull(endpointClass, "endpointClass is required");
this.handlerProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass); this.endpointProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
this.endpoint = null;
} }
@ -81,14 +83,14 @@ public class EndpointConnectionManager extends EndpointConnectionManagerSupport
@Override @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.handlerProvider instanceof BeanFactoryAware) { if (this.endpointProvider != null) {
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory); this.endpointProvider.setBeanFactory(beanFactory);
} }
} }
@Override @Override
protected void openConnection() throws Exception { protected void openConnection() throws Exception {
Endpoint endpoint = this.handlerProvider.getHandler(); Endpoint endpoint = (this.endpoint != null) ? this.endpoint : this.endpointProvider.getHandler();
ClientEndpointConfig endpointConfig = this.configBuilder.build(); ClientEndpointConfig endpointConfig = this.configBuilder.build();
Session session = getWebSocketContainer().connectToServer(endpoint, endpointConfig, getUri()); Session session = getWebSocketContainer().connectToServer(endpoint, endpointConfig, getUri());
updateSession(session); updateSession(session);

View File

@ -32,14 +32,12 @@ import javax.websocket.WebSocketContainer;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession; import org.springframework.websocket.WebSocketSession;
import org.springframework.websocket.adapter.StandardWebSocketSessionAdapter;
import org.springframework.websocket.adapter.StandardEndpointAdapter; import org.springframework.websocket.adapter.StandardEndpointAdapter;
import org.springframework.websocket.adapter.StandardWebSocketSessionAdapter;
import org.springframework.websocket.client.WebSocketClient; import org.springframework.websocket.client.WebSocketClient;
import org.springframework.websocket.client.WebSocketConnectFailureException; import org.springframework.websocket.client.WebSocketConnectFailureException;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* A standard Java {@link WebSocketClient}. * A standard Java {@link WebSocketClient}.
@ -61,24 +59,18 @@ public class StandardWebSocketClient implements WebSocketClient {
} }
@Override @Override
public WebSocketSession doHandshake(WebSocketHandler handler, String uriTemplate, Object... uriVariables) public WebSocketSession doHandshake(WebSocketHandler webSocketHandler, String uriTemplate, Object... uriVariables)
throws WebSocketConnectFailureException { throws WebSocketConnectFailureException {
return doHandshake(new SimpleHandlerProvider<WebSocketHandler<?>>(handler), uriTemplate, uriVariables);
}
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler,
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException {
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode().toUri(); URI uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode().toUri();
return doHandshake(handler, null, uri); return doHandshake(webSocketHandler, null, uri);
} }
@Override @Override
public WebSocketSession doHandshake(HandlerProvider<WebSocketHandler<?>> handler, public WebSocketSession doHandshake(WebSocketHandler<?> webSocketHandler,
final HttpHeaders httpHeaders, URI uri) throws WebSocketConnectFailureException { final HttpHeaders httpHeaders, URI uri) throws WebSocketConnectFailureException {
Endpoint endpoint = new StandardEndpointAdapter(handler); Endpoint endpoint = new StandardEndpointAdapter(webSocketHandler);
ClientEndpointConfig.Builder configBuidler = ClientEndpointConfig.Builder.create(); ClientEndpointConfig.Builder configBuidler = ClientEndpointConfig.Builder.create();
if (httpHeaders != null) { if (httpHeaders != null) {

View File

@ -35,7 +35,6 @@ import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -88,7 +87,7 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
@Override @Override
public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> handler) throws IOException { WebSocketHandler<?> webSocketHandler) throws IOException {
logger.debug("Starting handshake for " + request.getURI()); logger.debug("Starting handshake for " + request.getURI());
@ -136,10 +135,10 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
response.flush(); response.flush();
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Upgrading with " + handler); logger.trace("Upgrading with " + webSocketHandler);
} }
this.requestUpgradeStrategy.upgrade(request, response, selectedProtocol, handler); this.requestUpgradeStrategy.upgrade(request, response, selectedProtocol, webSocketHandler);
return true; return true;
} }

View File

@ -20,7 +20,6 @@ import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -33,6 +32,6 @@ public interface HandshakeHandler {
boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
HandlerProvider<WebSocketHandler<?>> handler) throws IOException; WebSocketHandler<?> webSocketHandler) throws IOException;
} }

View File

@ -20,7 +20,6 @@ import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
/** /**
@ -44,7 +43,6 @@ public interface RequestUpgradeStrategy {
* @param handler the handler for WebSocket messages * @param handler the handler for WebSocket messages
*/ */
void upgrade(ServerHttpRequest request, ServerHttpResponse response, String selectedProtocol, void upgrade(ServerHttpRequest request, ServerHttpResponse response, String selectedProtocol,
HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException; WebSocketHandler<?> webSocketHandler) throws IOException;
// FIXME how to indicate failure to upgrade?
} }

View File

@ -33,9 +33,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.support.BeanCreatingHandlerProvider; import org.springframework.websocket.support.BeanCreatingHandlerProvider;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
@ -53,7 +51,9 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
private final String path; private final String path;
private final HandlerProvider<Endpoint> handlerProvider; private final BeanCreatingHandlerProvider<Endpoint> endpointProvider;
private final Endpoint endpoint;
private List<Class<? extends Encoder>> encoders = new ArrayList<Class<? extends Encoder>>(); private List<Class<? extends Encoder>> encoders = new ArrayList<Class<? extends Encoder>>();
@ -70,7 +70,6 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
/** /**
* Class constructor with the {@code javax.webscoket.Endpoint} class. * Class constructor with the {@code javax.webscoket.Endpoint} class.
* TODO
* *
* @param path * @param path
* @param endpointClass * @param endpointClass
@ -79,14 +78,16 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
Assert.hasText(path, "path must not be empty"); Assert.hasText(path, "path must not be empty");
Assert.notNull(endpointClass, "endpointClass is required"); Assert.notNull(endpointClass, "endpointClass is required");
this.path = path; this.path = path;
this.handlerProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass); this.endpointProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
this.endpoint = null;
} }
public EndpointRegistration(String path, Endpoint endpointBean) { public EndpointRegistration(String path, Endpoint endpoint) {
Assert.hasText(path, "path must not be empty"); Assert.hasText(path, "path must not be empty");
Assert.notNull(endpointBean, "endpointBean is required"); Assert.notNull(endpoint, "endpoint is required");
this.path = path; this.path = path;
this.handlerProvider = new SimpleHandlerProvider<Endpoint>(endpointBean); this.endpointProvider = null;
this.endpoint = endpoint;
} }
@ -96,13 +97,13 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
} }
@Override @Override
@SuppressWarnings("unchecked")
public Class<? extends Endpoint> getEndpointClass() { public Class<? extends Endpoint> getEndpointClass() {
return (Class<? extends Endpoint>) this.handlerProvider.getHandlerType(); return (this.endpoint != null) ?
this.endpoint.getClass() : ((Class<? extends Endpoint>) this.endpointProvider.getHandlerType());
} }
public Endpoint getEndpoint() { public Endpoint getEndpoint() {
return this.handlerProvider.getHandler(); return (this.endpoint != null) ? this.endpoint : this.endpointProvider.getHandler();
} }
public void setSubprotocols(List<String> subprotocols) { public void setSubprotocols(List<String> subprotocols) {
@ -115,7 +116,6 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
} }
public void setExtensions(List<Extension> extensions) { public void setExtensions(List<Extension> extensions) {
// TODO: verify against ServerContainer.getInstalledExtensions()
this.extensions = extensions; this.extensions = extensions;
} }
@ -188,8 +188,8 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
@Override @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.handlerProvider instanceof BeanFactoryAware) { if (this.endpointProvider != null) {
((BeanFactoryAware) this.handlerProvider).setBeanFactory(beanFactory); this.endpointProvider.setBeanFactory(beanFactory);
} }
} }

View File

@ -24,7 +24,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.adapter.StandardEndpointAdapter; import org.springframework.websocket.adapter.StandardEndpointAdapter;
import org.springframework.websocket.server.RequestUpgradeStrategy; import org.springframework.websocket.server.RequestUpgradeStrategy;
@ -43,9 +42,9 @@ public abstract class AbstractEndpointUpgradeStrategy implements RequestUpgradeS
@Override @Override
public void upgrade(ServerHttpRequest request, ServerHttpResponse response, public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
String protocol, HandlerProvider<WebSocketHandler<?>> handler) throws IOException { String protocol, WebSocketHandler<?> webSocketHandler) throws IOException {
upgradeInternal(request, response, protocol, new StandardEndpointAdapter(handler)); upgradeInternal(request, response, protocol, new StandardEndpointAdapter(webSocketHandler));
} }
protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response, protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,

View File

@ -32,7 +32,6 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.adapter.JettyWebSocketListenerAdapter; import org.springframework.websocket.adapter.JettyWebSocketListenerAdapter;
import org.springframework.websocket.server.RequestUpgradeStrategy; import org.springframework.websocket.server.RequestUpgradeStrategy;
@ -63,14 +62,12 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
this.factory = new WebSocketServerFactory(); this.factory = new WebSocketServerFactory();
this.factory.setCreator(new WebSocketCreator() { this.factory.setCreator(new WebSocketCreator() {
@Override @Override
@SuppressWarnings("unchecked")
public Object createWebSocket(UpgradeRequest request, UpgradeResponse response) { public Object createWebSocket(UpgradeRequest request, UpgradeResponse response) {
Assert.isInstanceOf(ServletWebSocketRequest.class, request); Assert.isInstanceOf(ServletWebSocketRequest.class, request);
ServletWebSocketRequest servletRequest = (ServletWebSocketRequest) request; ServletWebSocketRequest servletRequest = (ServletWebSocketRequest) request;
HandlerProvider<WebSocketHandler<?>> handlerProvider = WebSocketHandler<?> webSocketHandler =
(HandlerProvider<WebSocketHandler<?>>) servletRequest.getServletAttributes().get( (WebSocketHandler<?>) servletRequest.getServletAttributes().get(HANDLER_PROVIDER_ATTR_NAME);
HANDLER_PROVIDER_ATTR_NAME); return new JettyWebSocketListenerAdapter(webSocketHandler);
return new JettyWebSocketListenerAdapter(handlerProvider);
} }
}); });
try { try {
@ -89,7 +86,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
@Override @Override
public void upgrade(ServerHttpRequest request, ServerHttpResponse response, public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
String selectedProtocol, HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException { String selectedProtocol, WebSocketHandler<?> webSocketHandler) throws IOException {
Assert.isInstanceOf(ServletServerHttpRequest.class, request); Assert.isInstanceOf(ServletServerHttpRequest.class, request);
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
@ -97,16 +94,16 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy {
Assert.isInstanceOf(ServletServerHttpResponse.class, response); Assert.isInstanceOf(ServletServerHttpResponse.class, response);
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse(); HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
upgrade(servletRequest, servletResponse, selectedProtocol, handlerProvider); upgrade(servletRequest, servletResponse, selectedProtocol, webSocketHandler);
} }
private void upgrade(HttpServletRequest request, HttpServletResponse response, private void upgrade(HttpServletRequest request, HttpServletResponse response,
String selectedProtocol, final HandlerProvider<WebSocketHandler<?>> handlerProvider) throws IOException { String selectedProtocol, final WebSocketHandler<?> webSocketHandler) throws IOException {
Assert.state(this.factory.isUpgradeRequest(request, response), "Not a suitable WebSocket upgrade request"); Assert.state(this.factory.isUpgradeRequest(request, response), "Not a suitable WebSocket upgrade request");
Assert.state(this.factory.acceptWebSocket(request, response), "Unable to accept WebSocket"); Assert.state(this.factory.acceptWebSocket(request, response), "Unable to accept WebSocket");
request.setAttribute(HANDLER_PROVIDER_ATTR_NAME, handlerProvider); request.setAttribute(HANDLER_PROVIDER_ATTR_NAME, webSocketHandler);
} }
} }

View File

@ -29,11 +29,9 @@ import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.HttpRequestHandler; import org.springframework.web.HttpRequestHandler;
import org.springframework.web.util.NestedServletException; import org.springframework.web.util.NestedServletException;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler; import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.server.DefaultHandshakeHandler; import org.springframework.websocket.server.DefaultHandshakeHandler;
import org.springframework.websocket.server.HandshakeHandler; import org.springframework.websocket.server.HandshakeHandler;
import org.springframework.websocket.support.SimpleHandlerProvider;
/** /**
* An {@link HttpRequestHandler} that wraps the invocation of a {@link HandshakeHandler}. * An {@link HttpRequestHandler} that wraps the invocation of a {@link HandshakeHandler}.
@ -45,22 +43,17 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler {
private final HandshakeHandler handshakeHandler; private final HandshakeHandler handshakeHandler;
private final HandlerProvider<WebSocketHandler<?>> handlerProvider; private final WebSocketHandler<?> webSocketHandler;
public WebSocketHttpRequestHandler(WebSocketHandler webSocketHandler) { public WebSocketHttpRequestHandler(WebSocketHandler webSocketHandler) {
this(new SimpleHandlerProvider<WebSocketHandler<?>>(webSocketHandler)); this(webSocketHandler, new DefaultHandshakeHandler());
} }
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler<?>> handlerProvider) { public WebSocketHttpRequestHandler( WebSocketHandler<?> webSocketHandler, HandshakeHandler handshakeHandler) {
this(handlerProvider, new DefaultHandshakeHandler()); Assert.notNull(webSocketHandler, "webSocketHandler is required");
}
public WebSocketHttpRequestHandler( HandlerProvider<WebSocketHandler<?>> handlerProvider,
HandshakeHandler handshakeHandler) {
Assert.notNull(handlerProvider, "handlerProvider is required");
Assert.notNull(handshakeHandler, "handshakeHandler is required"); Assert.notNull(handshakeHandler, "handshakeHandler is required");
this.handlerProvider = handlerProvider; this.webSocketHandler = webSocketHandler;
this.handshakeHandler = new DefaultHandshakeHandler(); this.handshakeHandler = new DefaultHandshakeHandler();
} }
@ -72,7 +65,7 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler {
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response); ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
try { try {
this.handshakeHandler.doHandshake(httpRequest, httpResponse, this.handlerProvider); this.handshakeHandler.doHandshake(httpRequest, httpResponse, this.webSocketHandler);
} }
catch (Exception e) { catch (Exception e) {
// TODO // TODO

View File

@ -24,16 +24,13 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.websocket.HandlerProvider;
/** /**
* A {@link HandlerProvider} that uses {@link AutowireCapableBeanFactory#createBean(Class)
* creating a fresh instance every time #getHandler() is called.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 4.0 * @since 4.0
*/ */
public class BeanCreatingHandlerProvider<T> implements HandlerProvider<T>, BeanFactoryAware { public class BeanCreatingHandlerProvider<T> implements BeanFactoryAware {
private static final Log logger = LogFactory.getLog(BeanCreatingHandlerProvider.class); private static final Log logger = LogFactory.getLog(BeanCreatingHandlerProvider.class);
@ -76,7 +73,6 @@ public class BeanCreatingHandlerProvider<T> implements HandlerProvider<T>, BeanF
} }
} }
@Override
public void destroy(T handler) { public void destroy(T handler) {
if (this.beanFactory != null) { if (this.beanFactory != null) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {

View File

@ -0,0 +1,132 @@
/*
* Copyright 2002-2013 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.websocket.support;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.core.GenericTypeResolver;
import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus;
import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketMessage;
import org.springframework.websocket.WebSocketSession;
/**
* A {@link WebSocketHandler} that initializes and destroys a {@link WebSocketHandler}
* instance for each WebSocket connection and delegates all other methods to it.
*
* <p>
* Essentially create an instance of this class once, providing the type of
* {@link WebSocketHandler} class to create for each connection, and then pass it to any
* API method that expects a {@link WebSocketHandler}.
*
* <p>
* If initializing the target {@link WebSocketHandler} type requires a Spring BeanFctory,
* then the {@link #setBeanFactory(BeanFactory)} property accordingly. Simply declaring
* this class as a Spring bean will do that. Otherwise, {@link WebSocketHandler} instances
* of the target type will be created using the default constructor.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class PerConnectionWebSocketHandlerProxy implements WebSocketHandler<WebSocketMessage<?>>, BeanFactoryAware {
private Log logger = LogFactory.getLog(PerConnectionWebSocketHandlerProxy.class);
private final BeanCreatingHandlerProvider<WebSocketHandler<?>> provider;
private Map<WebSocketSession, WebSocketHandler<?>> handlers =
new ConcurrentHashMap<WebSocketSession, WebSocketHandler<?>>();
private final Class<?> supportedMessageType;
public PerConnectionWebSocketHandlerProxy(Class<? extends WebSocketHandler<?>> handlerType) {
this.provider = new BeanCreatingHandlerProvider<WebSocketHandler<?>>(handlerType);
this.supportedMessageType = GenericTypeResolver.resolveTypeArgument(handlerType, WebSocketHandler.class);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.provider.setBeanFactory(beanFactory);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) {
WebSocketHandler<?> handler = this.provider.getHandler();
this.handlers.put(session, handler);
handler.afterConnectionEstablished(session);
}
@SuppressWarnings("unchecked")
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (!this.supportedMessageType.isAssignableFrom(message.getClass())) {
try {
session.close(CloseStatus.NOT_ACCEPTABLE.withReason("Message type not supported"));
}
catch (IOException e) {
destroy(session);
}
}
else {
((WebSocketHandler) getHandler(session)).handleMessage(session, message);
}
}
private WebSocketHandler<?> getHandler(WebSocketSession session) {
WebSocketHandler<?> handler = this.handlers.get(session);
Assert.isTrue(handler != null, "WebSocketHandler not found for " + session);
return handler;
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
getHandler(session).handleTransportError(session, exception);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
try {
getHandler(session).afterConnectionClosed(session, closeStatus);
}
finally {
destroy(session);
}
}
private void destroy(WebSocketSession session) {
WebSocketHandler<?> handler = this.handlers.remove(session);
try {
if (handler != null) {
this.provider.destroy(handler);
}
}
catch (Throwable t) {
logger.warn("Error while destroying handler", t);
}
}
}

View File

@ -1,62 +0,0 @@
/*
* Copyright 2002-2013 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.websocket.support;
import org.springframework.util.ClassUtils;
import org.springframework.websocket.HandlerProvider;
/**
* A {@link HandlerProvider} that returns a singleton instance.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class SimpleHandlerProvider<T> implements HandlerProvider<T> {
private final T handler;
public SimpleHandlerProvider(T handler) {
this.handler = handler;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<?> getHandlerType() {
return ClassUtils.getUserClass(this.handler);
}
@Override
public T getHandler() {
return this.handler;
}
@Override
public void destroy(T handler) {
}
@Override
public String toString() {
return "SimpleHandlerProvider [handler=" + handler + "]";
}
}