diff --git a/build.gradle b/build.gradle
index e8986cd15ad..1708b1587c5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -515,6 +515,7 @@ project("spring-websocket") {
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-web"))
+ optional(project(":spring-webmvc"))
optional("org.apache.tomcat:tomcat-servlet-api:8.0-SNAPSHOT") // TODO: replace with "javax.servlet:javax.servlet-api"
optional("org.apache.tomcat:tomcat-websocket-api:8.0-SNAPSHOT") // TODO: replace with "javax.websocket:javax.websocket-api"
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSession.java
index 89941b9840b..67e193f314b 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSession.java
@@ -17,12 +17,9 @@
package org.springframework.sockjs.server;
import java.io.EOFException;
-import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
-import org.springframework.sockjs.server.SockJsConfiguration;
-import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.SockJsSession;
import org.springframework.sockjs.SockJsSessionSupport;
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractSockJsService.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractSockJsService.java
index d56303fa0e6..fb7c5edcf53 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractSockJsService.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractSockJsService.java
@@ -32,9 +32,7 @@ import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.TransportType;
-import org.springframework.sockjs.server.support.DefaultTransportHandlerRegistrar;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
@@ -56,7 +54,7 @@ public abstract class AbstractSockJsService implements SockJsConfiguration {
private static final int ONE_YEAR = 365 * 24 * 60 * 60;
- private String sockJsServiceName = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
+ private final String prefix;
private String clientLibraryUrl = "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js";
@@ -78,31 +76,28 @@ public abstract class AbstractSockJsService implements SockJsConfiguration {
/**
* Class constructor...
*
+ * @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 AbstractSockJsService() {
+ public AbstractSockJsService(String prefix) {
+ Assert.hasText(prefix, "prefix is required");
+ this.prefix = prefix;
this.heartbeatScheduler = createScheduler("SockJs-heartbeat-");
}
protected TaskScheduler createScheduler(String threadNamePrefix) {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix(threadNamePrefix);
+ scheduler.afterPropertiesSet();
return scheduler;
}
/**
- * A unique name for the service, possibly the prefix at which it is deployed.
- * Used mainly for logging purposes.
+ * The path prefix to which the SockJS service is mapped.
*/
- public void setSockJsServiceName(String serviceName) {
- this.sockJsServiceName = serviceName;
- }
-
- /**
- * The SockJS service name.
- * @see #setSockJsServiceName(String)
- */
- public String getSockJsServiceName() {
- return this.sockJsServiceName;
+ public String getPrefix() {
+ return this.prefix;
}
/**
@@ -178,9 +173,8 @@ public abstract class AbstractSockJsService implements SockJsConfiguration {
this.heartbeatScheduler = heartbeatScheduler;
}
- public AbstractSockJsService setDisconnectDelay(long disconnectDelay) {
+ public void setDisconnectDelay(long disconnectDelay) {
this.disconnectDelay = disconnectDelay;
- return this;
}
public long getDisconnectDelay() {
@@ -193,9 +187,8 @@ public abstract class AbstractSockJsService implements SockJsConfiguration {
*
* The default value is "true".
*/
- public AbstractSockJsService setWebSocketsEnabled(boolean webSocketsEnabled) {
+ public void setWebSocketsEnabled(boolean webSocketsEnabled) {
this.webSocketsEnabled = webSocketsEnabled;
- return this;
}
/**
@@ -212,9 +205,8 @@ public abstract class AbstractSockJsService implements SockJsConfiguration {
* heartbeats, only raw WebSocket protocol. This property allows setting a
* handler for requests for raw WebSocket communication.
*/
- public AbstractSockJsService setWebsocketHandler(HandshakeRequestHandler handshakeRequestHandler) {
+ public void setWebsocketHandler(HandshakeRequestHandler handshakeRequestHandler) {
this.handshakeRequestHandler = handshakeRequestHandler;
- return this;
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/WebSocketSockJsHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketHandler.java
similarity index 78%
rename from spring-websocket/src/main/java/org/springframework/sockjs/server/WebSocketSockJsHandlerAdapter.java
rename to spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketHandler.java
index 95bb75ff086..b2719948620 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/WebSocketSockJsHandlerAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketHandler.java
@@ -29,38 +29,41 @@ import com.fasterxml.jackson.databind.ObjectMapper;
/**
+ * An implementation of {@link WebSocketHandler} supporting the SockJS protocol.
+ * Methods merely delegate to a {@link StandardWebSocketServerSession}.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class WebSocketSockJsHandlerAdapter implements WebSocketHandler {
+public class SockJsWebSocketHandler implements WebSocketHandler {
- private static final Log logger = LogFactory.getLog(WebSocketSockJsHandlerAdapter.class);
+ private static final Log logger = LogFactory.getLog(SockJsWebSocketHandler.class);
- private final SockJsWebSocketSessionAdapter sockJsSession;
+ private final StandardWebSocketServerSession sockJsSession;
// TODO: the JSON library used must be configurable
private final ObjectMapper objectMapper = new ObjectMapper();
- public WebSocketSockJsHandlerAdapter(SockJsWebSocketSessionAdapter sockJsSession) {
+ public SockJsWebSocketHandler(StandardWebSocketServerSession sockJsSession) {
this.sockJsSession = sockJsSession;
}
@Override
public void newSession(WebSocketSession webSocketSession) throws Exception {
- logger.debug("WebSocket connection established");
- webSocketSession.sendText(SockJsFrame.openFrame().getContent());
+ if (logger.isDebugEnabled()) {
+ logger.debug("New session: " + webSocketSession);
+ }
this.sockJsSession.setWebSocketSession(webSocketSession);
}
@Override
public void handleTextMessage(WebSocketSession session, String message) throws Exception {
- if (logger.isDebugEnabled()) {
- logger.debug("Received payload " + message + " for " + sockJsSession);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Received payload " + message + " for " + sockJsSession);
}
if (StringUtils.isEmpty(message)) {
- logger.debug("Ignoring empty payload");
+ logger.trace("Ignoring empty payload");
return;
}
try {
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketSessionAdapter.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/StandardWebSocketServerSession.java
similarity index 81%
rename from spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketSessionAdapter.java
rename to spring-websocket/src/main/java/org/springframework/sockjs/server/StandardWebSocketServerSession.java
index ea2610ab0d9..183e964305b 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsWebSocketSessionAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/StandardWebSocketServerSession.java
@@ -27,26 +27,27 @@ import org.springframework.websocket.WebSocketSession;
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class SockJsWebSocketSessionAdapter extends AbstractServerSession {
+public class StandardWebSocketServerSession extends AbstractServerSession {
- private static Log logger = LogFactory.getLog(SockJsWebSocketSessionAdapter.class);
+ private static Log logger = LogFactory.getLog(StandardWebSocketServerSession.class);
private WebSocketSession webSocketSession;
- public SockJsWebSocketSessionAdapter(String sessionId, SockJsHandler delegate, SockJsConfiguration sockJsConfig) {
+ public StandardWebSocketServerSession(String sessionId, SockJsHandler delegate, SockJsConfiguration sockJsConfig) {
super(sessionId, delegate, sockJsConfig);
}
public void setWebSocketSession(WebSocketSession webSocketSession) throws Exception {
this.webSocketSession = webSocketSession;
+ webSocketSession.sendText(SockJsFrame.openFrame().getContent());
scheduleHeartbeat();
connectionInitialized();
}
@Override
public boolean isActive() {
- return (this.webSocketSession != null);
+ return ((this.webSocketSession != null) && this.webSocketSession.isOpen());
}
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultSockJsService.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultSockJsService.java
index c00c49222ad..d6dcb875627 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultSockJsService.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultSockJsService.java
@@ -64,7 +64,8 @@ public class DefaultSockJsService extends AbstractSockJsService implements Trans
* Class constructor...
*
*/
- public DefaultSockJsService(SockJsHandler sockJsHandler) {
+ public DefaultSockJsService(String prefix, SockJsHandler sockJsHandler) {
+ super(prefix);
Assert.notNull(sockJsHandler, "sockJsHandler is required");
this.sockJsHandler = sockJsHandler;
this.sessionTimeoutScheduler = createScheduler("SockJs-sessionTimeout-");
@@ -105,23 +106,23 @@ public class DefaultSockJsService extends AbstractSockJsService implements Trans
try {
int count = sessions.size();
if (logger.isTraceEnabled() && (count != 0)) {
- logger.trace("Checking " + count + " session(s) for timeouts [" + getSockJsServiceName() + "]");
+ logger.trace("Checking " + count + " session(s) for timeouts [" + getPrefix() + "]");
}
for (SockJsSessionSupport session : sessions.values()) {
if (session.getTimeSinceLastActive() > getDisconnectDelay()) {
if (logger.isTraceEnabled()) {
- logger.trace("Removing " + session + " for [" + getSockJsServiceName() + "]");
+ logger.trace("Removing " + session + " for [" + getPrefix() + "]");
}
session.close();
sessions.remove(session.getId());
}
}
if (logger.isTraceEnabled() && (count != 0)) {
- logger.trace(sessions.size() + " remaining session(s) [" + getSockJsServiceName() + "]");
+ logger.trace(sessions.size() + " remaining session(s) [" + getPrefix() + "]");
}
}
catch (Throwable t) {
- logger.error("Failed to complete session timeout checks for [" + getSockJsServiceName() + "]", t);
+ logger.error("Failed to complete session timeout checks for [" + getPrefix() + "]", t);
}
}
}, getDisconnectDelay());
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultTransportHandlerRegistrar.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultTransportHandlerRegistrar.java
index a6c50e49779..6f41298d60c 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultTransportHandlerRegistrar.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/DefaultTransportHandlerRegistrar.java
@@ -21,6 +21,7 @@ import org.springframework.sockjs.server.transport.EventSourceTransportHandler;
import org.springframework.sockjs.server.transport.HtmlFileTransportHandler;
import org.springframework.sockjs.server.transport.JsonpPollingTransportHandler;
import org.springframework.sockjs.server.transport.JsonpTransportHandler;
+import org.springframework.sockjs.server.transport.WebSocketTransportHandler;
import org.springframework.sockjs.server.transport.XhrPollingTransportHandler;
import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler;
import org.springframework.sockjs.server.transport.XhrTransportHandler;
@@ -36,6 +37,8 @@ public class DefaultTransportHandlerRegistrar implements TransportHandlerRegistr
public void registerTransportHandlers(TransportHandlerRegistry registry) {
+ registry.registerHandler(new WebSocketTransportHandler());
+
registry.registerHandler(new XhrPollingTransportHandler());
registry.registerHandler(new XhrTransportHandler());
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHandlerMapping.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHandlerMapping.java
new file mode 100644
index 00000000000..c40565ecacf
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHandlerMapping.java
@@ -0,0 +1,70 @@
+/*
+ * 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.sockjs.server.support;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.sockjs.server.AbstractSockJsService;
+import org.springframework.web.servlet.handler.AbstractHandlerMapping;
+
+/**
+ * A Spring MVC HandlerMapping matching requests to SockJS services by prefix.
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ */
+public class SockJsServiceHandlerMapping extends AbstractHandlerMapping {
+
+ private static Log logger = LogFactory.getLog(SockJsServiceHandlerMapping.class);
+
+ private final List sockJsServices;
+
+
+ public SockJsServiceHandlerMapping(AbstractSockJsService... sockJsServices) {
+ this.sockJsServices = Arrays.asList(sockJsServices);
+ }
+
+ @Override
+ protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
+
+ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Looking for SockJS service match to path " + lookupPath);
+ }
+
+ for (AbstractSockJsService service : this.sockJsServices) {
+ if (lookupPath.startsWith(service.getPrefix())) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Matched to " + service);
+ }
+ String sockJsPath = lookupPath.substring(service.getPrefix().length());
+ return new SockJsServiceHttpRequestHandler(sockJsPath, service);
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Did not find a match");
+ }
+
+ return null;
+ }
+
+}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHttpRequestHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHttpRequestHandler.java
new file mode 100644
index 00000000000..57d3baf3330
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsServiceHttpRequestHandler.java
@@ -0,0 +1,66 @@
+/*
+ * 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.sockjs.server.support;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.http.server.AsyncServletServerHttpRequest;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpResponse;
+import org.springframework.sockjs.server.AbstractSockJsService;
+import org.springframework.web.HttpRequestHandler;
+import org.springframework.web.util.NestedServletException;
+
+/**
+ * A Spring MVC {@link HttpRequestHandler} wrapping the invocation of a SockJS service.
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ */
+public class SockJsServiceHttpRequestHandler implements HttpRequestHandler {
+
+ private final String sockJsPath;
+
+ private final AbstractSockJsService sockJsService;
+
+
+ public SockJsServiceHttpRequestHandler(String sockJsPath, AbstractSockJsService sockJsService) {
+ this.sockJsService = sockJsService;
+ this.sockJsPath = sockJsPath;
+ }
+
+ @Override
+ public void handleRequest(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ ServerHttpRequest httpRequest = new AsyncServletServerHttpRequest(request, response);
+ ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
+
+ try {
+ this.sockJsService.handleRequest(httpRequest, httpResponse, this.sockJsPath);
+ }
+ catch (Exception ex) {
+ // TODO
+ throw new NestedServletException("SockJS service failure", ex);
+ }
+ }
+
+}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpSendingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpSendingTransportHandler.java
index 90ef3c29a62..9a59a79e674 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpSendingTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpSendingTransportHandler.java
@@ -15,6 +15,8 @@
*/
package org.springframework.sockjs.server.transport;
+import java.io.IOException;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.MediaType;
@@ -37,14 +39,19 @@ public abstract class AbstractHttpSendingTransportHandler implements TransportHa
@Override
- public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, SockJsSessionSupport session)
- throws Exception {
-
- AbstractHttpServerSession httpServerSession = (AbstractHttpServerSession) session;
+ public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
+ SockJsSessionSupport session) throws Exception {
// Set content type before writing
response.getHeaders().setContentType(getContentType());
+ AbstractHttpServerSession httpServerSession = (AbstractHttpServerSession) session;
+ handleRequestInternal(request, response, httpServerSession);
+ }
+
+ protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
+ AbstractHttpServerSession httpServerSession) throws Exception, IOException {
+
if (httpServerSession.isNew()) {
handleNewSession(request, response, httpServerSession);
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractStreamingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractStreamingTransportHandler.java
index 10816de521c..e7740d6d490 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractStreamingTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractStreamingTransportHandler.java
@@ -20,7 +20,6 @@ import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.sockjs.SockJsHandler;
-import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.server.SockJsConfiguration;
@@ -39,12 +38,11 @@ public abstract class AbstractStreamingTransportHandler extends AbstractHttpSend
}
@Override
- public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, SockJsSessionSupport session)
- throws Exception {
+ public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
+ AbstractHttpServerSession session) throws Exception {
writePrelude(request, response);
-
- super.handleRequest(request, response, session);
+ super.handleRequestInternal(request, response, session);
}
protected abstract void writePrelude(ServerHttpRequest request, ServerHttpResponse response)
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/HtmlFileTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/HtmlFileTransportHandler.java
index cc1e98ac224..adc983e0b41 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/HtmlFileTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/HtmlFileTransportHandler.java
@@ -22,7 +22,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.TransportType;
import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
@@ -78,8 +77,8 @@ public class HtmlFileTransportHandler extends AbstractStreamingTransportHandler
}
@Override
- public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, SockJsSessionSupport session)
- throws Exception {
+ public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
+ AbstractHttpServerSession session) throws Exception {
String callback = request.getQueryParams().getFirst("c");
if (! StringUtils.hasText(callback)) {
@@ -87,8 +86,7 @@ public class HtmlFileTransportHandler extends AbstractStreamingTransportHandler
response.getBody().write("\"callback\" parameter required".getBytes("UTF-8"));
return;
}
-
- super.handleRequest(request, response, session);
+ super.handleRequestInternal(request, response, session);
}
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpPollingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpPollingTransportHandler.java
index c696c6cf127..bff94ad72e8 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpPollingTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpPollingTransportHandler.java
@@ -22,7 +22,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.sockjs.SockJsHandler;
-import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.TransportType;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
@@ -56,8 +55,8 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
}
@Override
- public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, SockJsSessionSupport session)
- throws Exception {
+ public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
+ AbstractHttpServerSession session) throws Exception {
String callback = request.getQueryParams().getFirst("c");
if (! StringUtils.hasText(callback)) {
@@ -65,7 +64,6 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
response.getBody().write("\"callback\" parameter required".getBytes("UTF-8"));
return;
}
-
super.handleRequest(request, response, session);
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingHttpServerSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingHttpServerSession.java
index d327568331f..2eb846683fc 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingHttpServerSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingHttpServerSession.java
@@ -43,7 +43,8 @@ public class StreamingHttpServerSession extends AbstractHttpServerSession {
this.byteCount += frame.getContentBytes().length + 1;
if (logger.isTraceEnabled()) {
- logger.trace(this.byteCount + " bytes written, " + getMessageCache().size() + " more messages");
+ logger.trace(this.byteCount + " bytes written so far, "
+ + getMessageCache().size() + " more messages not flushed");
}
if (this.byteCount >= getSockJsConfig().getStreamBytesLimit()) {
if (logger.isTraceEnabled()) {
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketTransportHandler.java
index 9abf049b167..40ced92ad5e 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketTransportHandler.java
@@ -22,9 +22,9 @@ import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.TransportType;
import org.springframework.sockjs.server.SockJsConfiguration;
-import org.springframework.sockjs.server.SockJsWebSocketSessionAdapter;
+import org.springframework.sockjs.server.StandardWebSocketServerSession;
import org.springframework.sockjs.server.TransportHandler;
-import org.springframework.sockjs.server.WebSocketSockJsHandlerAdapter;
+import org.springframework.sockjs.server.SockJsWebSocketHandler;
import org.springframework.websocket.server.HandshakeRequestHandler;
import org.springframework.websocket.server.endpoint.EndpointHandshakeRequestHandler;
@@ -44,15 +44,15 @@ public class WebSocketTransportHandler implements TransportHandler {
@Override
public SockJsSessionSupport createSession(String sessionId, SockJsHandler handler, SockJsConfiguration config) {
- return new SockJsWebSocketSessionAdapter(sessionId, handler, config);
+ return new StandardWebSocketServerSession(sessionId, handler, config);
}
@Override
public void handleRequest(ServerHttpRequest request, ServerHttpResponse response, SockJsSessionSupport session)
throws Exception {
- SockJsWebSocketSessionAdapter sockJsSession = (SockJsWebSocketSessionAdapter) session;
- WebSocketSockJsHandlerAdapter webSocketHandler = new WebSocketSockJsHandlerAdapter(sockJsSession);
+ StandardWebSocketServerSession sockJsSession = (StandardWebSocketServerSession) session;
+ SockJsWebSocketHandler webSocketHandler = new SockJsWebSocketHandler(sockJsSession);
HandshakeRequestHandler handshakeRequestHandler = new EndpointHandshakeRequestHandler(webSocketHandler);
handshakeRequestHandler.doHandshake(request, response);
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java
index 947a565bb73..d930dde9d0f 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java
@@ -25,6 +25,8 @@ package org.springframework.websocket;
*/
public interface WebSocketSession {
+ boolean isOpen();
+
void sendText(String text) throws Exception;
void close();
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketStandardSessionAdapter.java b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
similarity index 76%
rename from spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketStandardSessionAdapter.java
rename to spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
index ce3dd1c5313..302a0333923 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketStandardSessionAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
@@ -22,21 +22,27 @@ import org.springframework.websocket.WebSocketSession;
/**
+ * A {@link WebSocketSession} that delegates to a {@link javax.websocket.Session}.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class WebSocketStandardSessionAdapter implements WebSocketSession {
+public class StandardWebSocketSession implements WebSocketSession {
- private static Log logger = LogFactory.getLog(WebSocketStandardSessionAdapter.class);
+ private static Log logger = LogFactory.getLog(StandardWebSocketSession.class);
private javax.websocket.Session session;
- public WebSocketStandardSessionAdapter(javax.websocket.Session session) {
+ public StandardWebSocketSession(javax.websocket.Session session) {
this.session = session;
}
+ @Override
+ public boolean isOpen() {
+ return ((this.session != null) && this.session.isOpen());
+ }
+
@Override
public void sendText(String text) throws Exception {
logger.trace("Sending text message: " + text);
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
similarity index 87%
rename from spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketHandlerAdapter.java
rename to spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
index 2722cb09eda..da3d7a768aa 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketHandlerAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
@@ -32,28 +32,31 @@ import org.springframework.websocket.WebSocketHandler;
/**
+ * An {@link Endpoint} that delegates to a {@link WebSocketHandler}.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class StandardWebSocketHandlerAdapter extends Endpoint {
+public class WebSocketHandlerEndpoint extends Endpoint {
- private static Log logger = LogFactory.getLog(StandardWebSocketHandlerAdapter.class);
+ private static Log logger = LogFactory.getLog(WebSocketHandlerEndpoint.class);
private final WebSocketHandler webSocketHandler;
private final Map sessionMap = new ConcurrentHashMap();
- public StandardWebSocketHandlerAdapter(WebSocketHandler webSocketHandler) {
+ public WebSocketHandlerEndpoint(WebSocketHandler webSocketHandler) {
this.webSocketHandler = webSocketHandler;
}
@Override
public void onOpen(javax.websocket.Session session, EndpointConfig config) {
- logger.debug("New WebSocket session: " + session);
+ if (logger.isDebugEnabled()) {
+ logger.debug("New session: " + session);
+ }
try {
- WebSocketSession webSocketSession = new WebSocketStandardSessionAdapter(session);
+ WebSocketSession webSocketSession = new StandardWebSocketSession(session);
this.sessionMap.put(session.getId(), webSocketSession);
session.addMessageHandler(new StandardMessageHandler(session.getId()));
this.webSocketHandler.newSession(webSocketSession);
@@ -75,7 +78,6 @@ public class StandardWebSocketHandlerAdapter extends Endpoint {
this.sessionMap.remove(id);
int code = closeReason.getCloseCode().getCode();
String reason = closeReason.getReasonPhrase();
- webSocketSession.close(code, reason);
this.webSocketHandler.sessionClosed(webSocketSession, code, reason);
}
catch (Throwable ex) {
@@ -119,7 +121,7 @@ public class StandardWebSocketHandlerAdapter extends Endpoint {
}
try {
WebSocketSession session = getSession(this.sessionId);
- StandardWebSocketHandlerAdapter.this.webSocketHandler.handleTextMessage(session, message);
+ WebSocketHandlerEndpoint.this.webSocketHandler.handleTextMessage(session, message);
}
catch (Throwable ex) {
// TODO
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointHandshakeRequestHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointHandshakeRequestHandler.java
index aae44c148cb..abb66ff4cc5 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointHandshakeRequestHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointHandshakeRequestHandler.java
@@ -23,7 +23,7 @@ import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.ClassUtils;
import org.springframework.websocket.WebSocketHandler;
-import org.springframework.websocket.endpoint.StandardWebSocketHandlerAdapter;
+import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
import org.springframework.websocket.server.AbstractHandshakeRequestHandler;
@@ -43,7 +43,7 @@ public class EndpointHandshakeRequestHandler extends AbstractHandshakeRequestHan
public EndpointHandshakeRequestHandler(WebSocketHandler webSocketHandler) {
- this(new StandardWebSocketHandlerAdapter(webSocketHandler));
+ this(new WebSocketHandlerEndpoint(webSocketHandler));
}
public EndpointHandshakeRequestHandler(Endpoint endpoint) {
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointRegistration.java b/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointRegistration.java
index 843cb075986..9dfc509042e 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointRegistration.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/endpoint/EndpointRegistration.java
@@ -36,14 +36,14 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
-import org.springframework.websocket.endpoint.StandardWebSocketHandlerAdapter;
+import org.springframework.websocket.endpoint.WebSocketHandlerEndpoint;
/**
* An implementation of {@link javax.websocket.server.ServerEndpointConfig} that also
* holds the target {@link javax.websocket.Endpoint} as a reference or a bean name.
* The target can also be {@link org.springframework.websocket.WebSocketHandler}, in
- * which case it will be adapted via {@link StandardWebSocketHandlerAdapter}.
+ * which case it will be adapted via {@link WebSocketHandlerEndpoint}.
*
*
* Beans of this type are detected by {@link EndpointExporter} and
@@ -60,9 +60,9 @@ public class EndpointRegistration implements ServerEndpointConfig, BeanFactoryAw
private final Object endpointBean;
- private List> encoders;
+ private List> encoders = new ArrayList>();
- private List> decoders;
+ private List> decoders = new ArrayList>();
private List subprotocols = new ArrayList();