diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionSupport.java b/spring-websocket/src/main/java/org/springframework/sockjs/AbstractSockJsSession.java
similarity index 74%
rename from spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionSupport.java
rename to spring-websocket/src/main/java/org/springframework/sockjs/AbstractSockJsSession.java
index 3cf7e61fc1..1f3e82541e 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionSupport.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/AbstractSockJsSession.java
@@ -16,12 +16,16 @@
package org.springframework.sockjs;
-import java.io.IOException;
+import java.net.URI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus;
+import org.springframework.websocket.TextMessage;
+import org.springframework.websocket.TextMessageHandler;
+import org.springframework.websocket.WebSocketHandler;
+import org.springframework.websocket.WebSocketSession;
/**
@@ -30,13 +34,13 @@ import org.springframework.websocket.CloseStatus;
* @author Rossen Stoyanchev
* @since 4.0
*/
-public abstract class SockJsSessionSupport implements SockJsSession {
+public abstract class AbstractSockJsSession implements WebSocketSession {
protected Log logger = LogFactory.getLog(this.getClass());
private final String sessionId;
- private final SockJsHandler sockJsHandler;
+ private final TextMessageHandler handler;
private State state = State.NEW;
@@ -48,19 +52,32 @@ public abstract class SockJsSessionSupport implements SockJsSession {
/**
*
* @param sessionId
- * @param sockJsHandler the recipient of SockJS messages
+ * @param handler the recipient of SockJS messages
*/
- public SockJsSessionSupport(String sessionId, SockJsHandler sockJsHandler) {
+ public AbstractSockJsSession(String sessionId, WebSocketHandler webSocketHandler) {
Assert.notNull(sessionId, "sessionId is required");
- Assert.notNull(sockJsHandler, "sockJsHandler is required");
+ Assert.notNull(webSocketHandler, "webSocketHandler is required");
+ Assert.isInstanceOf(TextMessageHandler.class, webSocketHandler, "Expected a TextMessageHandler");
this.sessionId = sessionId;
- this.sockJsHandler = sockJsHandler;
+ this.handler = (TextMessageHandler) webSocketHandler;
}
public String getId() {
return this.sessionId;
}
+ @Override
+ public boolean isSecure() {
+ // TODO
+ return false;
+ }
+
+ @Override
+ public URI getURI() {
+ // TODO
+ return null;
+ }
+
public boolean isNew() {
return State.NEW.equals(this.state);
}
@@ -104,26 +121,26 @@ public abstract class SockJsSessionSupport implements SockJsSession {
public void delegateConnectionEstablished() throws Exception {
this.state = State.OPEN;
- this.sockJsHandler.afterConnectionEstablished(this);
+ this.handler.afterConnectionEstablished(this);
}
public void delegateMessages(String[] messages) throws Exception {
for (String message : messages) {
- this.sockJsHandler.handleMessage(message, this);
+ this.handler.handleTextMessage(new TextMessage(message), this);
}
}
public void delegateError(Throwable ex) {
- this.sockJsHandler.handleError(ex, this);
+ this.handler.handleError(ex, this);
}
/**
* Invoked in reaction to the underlying connection being closed by the remote side
* (or the WebSocket container) in order to perform cleanup and notify the
- * {@link SockJsHandler}. This is in contrast to {@link #close()} that pro-actively
+ * {@link TextMessageHandler}. This is in contrast to {@link #close()} that pro-actively
* closes the connection.
*/
- public final void delegateConnectionClosed(CloseStatus status) {
+ public final void delegateConnectionClosed(CloseStatus status) throws Exception {
if (!isClosed()) {
if (logger.isDebugEnabled()) {
logger.debug(this + " was closed, " + status);
@@ -133,7 +150,7 @@ public abstract class SockJsSessionSupport implements SockJsSession {
}
finally {
this.state = State.CLOSED;
- this.sockJsHandler.afterConnectionClosed(status, this);
+ this.handler.afterConnectionClosed(status, this);
}
}
}
@@ -145,7 +162,7 @@ public abstract class SockJsSessionSupport implements SockJsSession {
* {@inheritDoc}
*
Performs cleanup and notifies the {@link SockJsHandler}.
*/
- public final void close() throws IOException {
+ public final void close() throws Exception {
close(CloseStatus.NORMAL);
}
@@ -153,7 +170,7 @@ public abstract class SockJsSessionSupport implements SockJsSession {
* {@inheritDoc}
*
Performs cleanup and notifies the {@link SockJsHandler}.
*/
- public final void close(CloseStatus status) throws IOException {
+ public final void close(CloseStatus status) throws Exception {
if (!isClosed()) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this + ", " + status);
@@ -163,12 +180,12 @@ public abstract class SockJsSessionSupport implements SockJsSession {
}
finally {
this.state = State.CLOSED;
- this.sockJsHandler.afterConnectionClosed(status, this);
+ this.handler.afterConnectionClosed(status, this);
}
}
}
- protected abstract void closeInternal(CloseStatus status) throws IOException;
+ protected abstract void closeInternal(CloseStatus status) throws Exception;
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandler.java
deleted file mode 100644
index e8c20e573f..0000000000
--- a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandler.java
+++ /dev/null
@@ -1,51 +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.sockjs;
-
-import org.springframework.websocket.CloseStatus;
-
-
-
-/**
- * A handler for SockJS messages.
- *
- * @author Rossen Stoyanchev
- * @since 4.0
- */
-public interface SockJsHandler {
-
- /**
- * A new connection was opened and is ready for use.
- */
- void afterConnectionEstablished(SockJsSession session) throws Exception;
-
- /**
- * Handle an incoming message.
- */
- void handleMessage(String message, SockJsSession session) throws Exception;
-
- /**
- * TODO
- */
- void handleError(Throwable exception, SockJsSession session);
-
- /**
- * A connection has been closed.
- */
- void afterConnectionClosed(CloseStatus status, SockJsSession session);
-
-}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSession.java
deleted file mode 100644
index e1e46155cd..0000000000
--- a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSession.java
+++ /dev/null
@@ -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.sockjs;
-
-import java.io.IOException;
-
-import org.springframework.websocket.CloseStatus;
-
-
-
-/**
- * Allows sending SockJS messages as well as closing the underlying connection.
- *
- * @author Rossen Stoyanchev
- * @since 4.0
- */
-public interface SockJsSession {
-
- /**
- * Return a unique SockJS session identifier.
- */
- String getId();
-
- /**
- * Return whether the connection is still open.
- */
- boolean isOpen();
-
- /**
- * Send a message.
- */
- void sendMessage(String text) throws IOException;
-
- /**
- * Close the underlying connection with status 1000, i.e. equivalent to:
- *
- * session.close(CloseStatus.NORMAL);
- *
- */
- void close() throws IOException;
-
- /**
- * Close the underlying connection with the given close status.
- */
- void close(CloseStatus status) throws IOException;
-
-
-}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionFactory.java b/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionFactory.java
index 4e4950181d..c87ff5a7b9 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionFactory.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/SockJsSessionFactory.java
@@ -16,6 +16,9 @@
package org.springframework.sockjs;
+import org.springframework.websocket.WebSocketHandler;
+import org.springframework.websocket.WebSocketSession;
+
/**
* A factory for creating a SockJS session.
@@ -23,8 +26,8 @@ package org.springframework.sockjs;
* @author Rossen Stoyanchev
* @since 4.0
*/
-public interface SockJsSessionFactory{
+public interface SockJsSessionFactory{
- S createSession(String sessionId, SockJsHandler sockJsHandler);
+ S createSession(String sessionId, WebSocketHandler webSocketHandler);
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSockJsSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSockJsSession.java
index 04fc33409d..51004660a6 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSockJsSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/AbstractServerSockJsSession.java
@@ -22,11 +22,12 @@ import java.net.SocketException;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
-import org.springframework.sockjs.SockJsHandler;
-import org.springframework.sockjs.SockJsSession;
-import org.springframework.sockjs.SockJsSessionSupport;
+import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus;
+import org.springframework.websocket.TextMessage;
+import org.springframework.websocket.WebSocketHandler;
+import org.springframework.websocket.WebSocketMessage;
/**
@@ -36,15 +37,17 @@ import org.springframework.websocket.CloseStatus;
* @author Rossen Stoyanchev
* @since 4.0
*/
-public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
+public abstract class AbstractServerSockJsSession extends AbstractSockJsSession {
private final SockJsConfiguration sockJsConfig;
private ScheduledFuture> heartbeatTask;
- public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config, SockJsHandler sockJsHandler) {
- super(sessionId, sockJsHandler);
+ public AbstractServerSockJsSession(String sessionId, SockJsConfiguration config,
+ WebSocketHandler webSocketHandler) {
+
+ super(sessionId, webSocketHandler);
this.sockJsConfig = config;
}
@@ -52,12 +55,13 @@ public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
return this.sockJsConfig;
}
- public final synchronized void sendMessage(String message) throws IOException {
+ public final synchronized void sendMessage(WebSocketMessage message) throws Exception {
Assert.isTrue(!isClosed(), "Cannot send a message, session has been closed");
- sendMessageInternal(message);
+ Assert.isInstanceOf(TextMessage.class, message, "Expected text message: " + message);
+ sendMessageInternal(((TextMessage) message).getPayload());
}
- protected abstract void sendMessageInternal(String message) throws IOException;
+ protected abstract void sendMessageInternal(String message) throws Exception;
@Override
@@ -67,7 +71,7 @@ public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
}
@Override
- public final synchronized void closeInternal(CloseStatus status) throws IOException {
+ public final synchronized void closeInternal(CloseStatus status) throws Exception {
if (isActive()) {
// TODO: deliver messages "in flight" before sending close frame
try {
@@ -84,13 +88,13 @@ public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
}
// TODO: close status/reason
- protected abstract void disconnect(CloseStatus status) throws IOException;
+ protected abstract void disconnect(CloseStatus status) throws Exception;
/**
* For internal use within a TransportHandler and the (TransportHandler-specific)
* session sub-class.
*/
- protected void writeFrame(SockJsFrame frame) throws IOException {
+ protected void writeFrame(SockJsFrame frame) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Preparing to write " + frame);
}
@@ -114,9 +118,9 @@ public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
}
}
- protected abstract void writeFrameInternal(SockJsFrame frame) throws IOException;
+ protected abstract void writeFrameInternal(SockJsFrame frame) throws Exception;
- public synchronized void sendHeartbeat() throws IOException {
+ public synchronized void sendHeartbeat() throws Exception {
if (isActive()) {
writeFrame(SockJsFrame.heartbeatFrame());
scheduleHeartbeat();
@@ -135,7 +139,7 @@ public abstract class AbstractServerSockJsSession extends SockJsSessionSupport {
try {
sendHeartbeat();
}
- catch (IOException e) {
+ catch (Exception e) {
// ignore
}
}
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 6d84713727..24c3dacb06 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
@@ -34,12 +34,12 @@ 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.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -218,7 +218,7 @@ public abstract class AbstractSockJsService
* @throws Exception
*/
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
- String sockJsPath, SockJsHandler sockJsHandler) throws Exception {
+ String sockJsPath, WebSocketHandler webSocketHandler) throws Exception {
logger.debug(request.getMethod() + " [" + sockJsPath + "]");
@@ -244,7 +244,7 @@ public abstract class AbstractSockJsService
return;
}
else if (sockJsPath.equals("/websocket")) {
- handleRawWebSocketRequest(request, response, sockJsHandler);
+ handleRawWebSocketRequest(request, response, webSocketHandler);
return;
}
@@ -264,7 +264,7 @@ public abstract class AbstractSockJsService
return;
}
- handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), sockJsHandler);
+ handleTransportRequest(request, response, sessionId, TransportType.fromValue(transport), webSocketHandler);
}
finally {
response.flush();
@@ -272,10 +272,10 @@ public abstract class AbstractSockJsService
}
protected abstract void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler) throws Exception;
+ WebSocketHandler webSocketHandler) throws Exception;
protected abstract void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
- String sessionId, TransportType transportType, SockJsHandler sockJsHandler) throws Exception;
+ String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception;
protected boolean validateRequest(String serverId, String sessionId, String transport) {
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/ConfigurableTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/ConfigurableTransportHandler.java
index 8ad26ef6fa..799ba50d89 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/ConfigurableTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/ConfigurableTransportHandler.java
@@ -16,11 +16,6 @@
package org.springframework.sockjs.server;
-import java.util.Collection;
-
-import org.springframework.sockjs.SockJsHandler;
-import org.springframework.websocket.WebSocketHandler;
-
/**
*
@@ -31,10 +26,4 @@ public interface ConfigurableTransportHandler extends TransportHandler {
void setSockJsConfiguration(SockJsConfiguration sockJsConfig);
- /**
- * Pre-register {@link SockJsHandler} instances so they can be adapted to
- * {@link WebSocketHandler} and hence re-used at runtime.
- */
- void registerSockJsHandlers(Collection sockJsHandlers);
-
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsService.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsService.java
index 23c79be7d2..604ddcbca1 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsService.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/SockJsService.java
@@ -16,11 +16,8 @@
package org.springframework.sockjs.server;
-import java.util.Collection;
-
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.websocket.WebSocketHandler;
@@ -31,15 +28,8 @@ import org.springframework.websocket.WebSocketHandler;
*/
public interface SockJsService {
- /**
- * Pre-register {@link SockJsHandler} instances so they can be adapted to
- * {@link WebSocketHandler} and hence re-used at runtime when
- * {@link #handleRequest(ServerHttpRequest, ServerHttpResponse, String, SockJsHandler) handleRequest}
- * is called.
- */
- void registerSockJsHandlers(Collection sockJsHandlers);
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, String sockJsPath,
- SockJsHandler handler) throws Exception;
+ WebSocketHandler webSocketHandler) throws Exception;
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/TransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/TransportHandler.java
index ea6208b836..8c662127d6 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/TransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/TransportHandler.java
@@ -17,8 +17,8 @@ package org.springframework.sockjs.server;
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.AbstractSockJsSession;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -31,6 +31,6 @@ public interface TransportHandler {
TransportType getTransportType();
void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler, SockJsSessionSupport session) throws Exception;
+ WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception;
}
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 60f8143f70..aa35115fe6 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
@@ -16,7 +16,6 @@
package org.springframework.sockjs.server.support;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -29,9 +28,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.scheduling.TaskScheduler;
-import org.springframework.sockjs.SockJsHandler;
+import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.sockjs.SockJsSessionFactory;
-import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.server.AbstractSockJsService;
import org.springframework.sockjs.server.ConfigurableTransportHandler;
import org.springframework.sockjs.server.TransportHandler;
@@ -40,7 +38,6 @@ 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.WebSocketSockJsHandlerAdapter;
import org.springframework.sockjs.server.transport.WebSocketTransportHandler;
import org.springframework.sockjs.server.transport.XhrPollingTransportHandler;
import org.springframework.sockjs.server.transport.XhrStreamingTransportHandler;
@@ -65,9 +62,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
private TaskSchedulerHolder sessionTimeoutSchedulerHolder;
- private final Map sessions = new ConcurrentHashMap();
-
- private final Map sockJsHandlers = new HashMap();
+ private final Map sessions = new ConcurrentHashMap();
public DefaultSockJsService() {
@@ -93,22 +88,6 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
}
}
- public void registerSockJsHandlers(Collection sockJsHandlers) {
- for (SockJsHandler sockJsHandler : sockJsHandlers) {
- if (!this.sockJsHandlers.containsKey(sockJsHandler)) {
- this.sockJsHandlers.put(sockJsHandler, adaptSockJsHandler(sockJsHandler));
- }
- }
- configureTransportHandlers();
- }
-
- /**
- * Adapt the {@link SockJsHandler} to the {@link WebSocketHandler} contract for
- * raw WebSocket communication on SockJS path "/websocket".
- */
- protected WebSocketSockJsHandlerAdapter adaptSockJsHandler(SockJsHandler sockJsHandler) {
- return new WebSocketSockJsHandlerAdapter(this, sockJsHandler);
- }
@Override
public void afterPropertiesSet() throws Exception {
@@ -135,7 +114,11 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
}
}
- configureTransportHandlers();
+ for (TransportHandler h : this.transportHandlers.values()) {
+ if (h instanceof ConfigurableTransportHandler) {
+ ((ConfigurableTransportHandler) h).setSockJsConfiguration(this);
+ }
+ }
this.sessionTimeoutSchedulerHolder.initialize();
@@ -146,7 +129,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
if (logger.isTraceEnabled() && (count != 0)) {
logger.trace("Checking " + count + " session(s) for timeouts [" + getName() + "]");
}
- for (SockJsSessionSupport session : sessions.values()) {
+ for (AbstractSockJsSession session : sessions.values()) {
if (session.getTimeSinceLastActive() > getDisconnectDelay()) {
if (logger.isTraceEnabled()) {
logger.trace("Removing " + session + " for [" + getName() + "]");
@@ -172,32 +155,14 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
this.sessionTimeoutSchedulerHolder.destroy();
}
- private void configureTransportHandlers() {
- for (TransportHandler h : this.transportHandlers.values()) {
- if (h instanceof ConfigurableTransportHandler) {
- ((ConfigurableTransportHandler) h).setSockJsConfiguration(this);
- if (!this.sockJsHandlers.isEmpty()) {
- ((ConfigurableTransportHandler) h).registerSockJsHandlers(this.sockJsHandlers.keySet());
- if (h instanceof HandshakeHandler) {
- ((HandshakeHandler) h).registerWebSocketHandlers(this.sockJsHandlers.values());
- }
- }
- }
- }
- }
-
@Override
protected void handleRawWebSocketRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler) throws Exception {
+ WebSocketHandler webSocketHandler) throws Exception {
if (isWebSocketEnabled()) {
TransportHandler transportHandler = this.transportHandlers.get(TransportType.WEBSOCKET);
if (transportHandler != null) {
if (transportHandler instanceof HandshakeHandler) {
- WebSocketHandler webSocketHandler = this.sockJsHandlers.get(sockJsHandler);
- if (webSocketHandler == null) {
- webSocketHandler = adaptSockJsHandler(sockJsHandler);
- }
((HandshakeHandler) transportHandler).doHandshake(request, response, webSocketHandler);
return;
}
@@ -209,7 +174,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
@Override
protected void handleTransportRequest(ServerHttpRequest request, ServerHttpResponse response,
- String sessionId, TransportType transportType, SockJsHandler sockJsHandler) throws Exception {
+ String sessionId, TransportType transportType, WebSocketHandler webSocketHandler) throws Exception {
TransportHandler transportHandler = this.transportHandlers.get(transportType);
@@ -236,7 +201,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
return;
}
- SockJsSessionSupport session = getSockJsSession(sessionId, sockJsHandler, transportHandler);
+ AbstractSockJsSession session = getSockJsSession(sessionId, webSocketHandler, transportHandler);
if (session != null) {
if (transportType.setsNoCacheHeader()) {
@@ -255,13 +220,13 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
}
}
- transportHandler.handleRequest(request, response, sockJsHandler, session);
+ transportHandler.handleRequest(request, response, webSocketHandler, session);
}
- public SockJsSessionSupport getSockJsSession(String sessionId, SockJsHandler sockJsHandler,
+ public AbstractSockJsSession getSockJsSession(String sessionId, WebSocketHandler webSocketHandler,
TransportHandler transportHandler) {
- SockJsSessionSupport session = this.sessions.get(sessionId);
+ AbstractSockJsSession session = this.sessions.get(sessionId);
if (session != null) {
return session;
}
@@ -275,7 +240,7 @@ public class DefaultSockJsService extends AbstractSockJsService implements Initi
return session;
}
logger.debug("Creating new session with session id \"" + sessionId + "\"");
- session = (SockJsSessionSupport) sessionFactory.createSession(sessionId, sockJsHandler);
+ session = (AbstractSockJsSession) sessionFactory.createSession(sessionId, webSocketHandler);
this.sessions.put(sessionId, session);
return session;
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsHttpRequestHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsHttpRequestHandler.java
index 22d058e0eb..b5e2b49caf 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsHttpRequestHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/support/SockJsHttpRequestHandler.java
@@ -17,7 +17,6 @@
package org.springframework.sockjs.server.support;
import java.io.IOException;
-import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -30,13 +29,13 @@ 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.SockJsHandler;
import org.springframework.sockjs.server.SockJsService;
import org.springframework.util.Assert;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.util.NestedServletException;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.websocket.HandlerProvider;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -50,7 +49,7 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
private final SockJsService sockJsService;
- private final HandlerProvider handlerProvider;
+ private final HandlerProvider handlerProvider;
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
@@ -62,16 +61,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
* 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, SockJsHandler sockJsHandler) {
+ public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService, WebSocketHandler webSocketHandler) {
Assert.hasText(prefix, "prefix is required");
Assert.notNull(sockJsService, "sockJsService is required");
- Assert.notNull(sockJsHandler, "sockJsHandler is required");
+ Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.prefix = prefix;
this.sockJsService = sockJsService;
- this.sockJsService.registerSockJsHandlers(Collections.singleton(sockJsHandler));
- this.handlerProvider = new HandlerProvider(sockJsHandler);
+ this.handlerProvider = new HandlerProvider(webSocketHandler);
}
/**
@@ -82,15 +80,15 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
* Servlet container this is the path within the current servlet mapping.
*/
public SockJsHttpRequestHandler(String prefix, SockJsService sockJsService,
- Class extends SockJsHandler> sockJsHandlerClass) {
+ Class extends WebSocketHandler> webSocketHandlerClass) {
Assert.hasText(prefix, "prefix is required");
Assert.notNull(sockJsService, "sockJsService is required");
- Assert.notNull(sockJsHandlerClass, "sockJsHandlerClass is required");
+ Assert.notNull(webSocketHandlerClass, "webSocketHandlerClass is required");
this.prefix = prefix;
this.sockJsService = sockJsService;
- this.handlerProvider = new HandlerProvider(sockJsHandlerClass);
+ this.handlerProvider = new HandlerProvider(webSocketHandlerClass);
}
public String getPrefix() {
@@ -121,8 +119,8 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler, BeanFactory
ServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
try {
- SockJsHandler sockJsHandler = this.handlerProvider.getHandler();
- this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, sockJsHandler);
+ WebSocketHandler webSocketHandler = this.handlerProvider.getHandler();
+ this.sockJsService.handleRequest(httpRequest, httpResponse, sockJsPath, webSocketHandler);
}
catch (Exception ex) {
// TODO
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpReceivingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpReceivingTransportHandler.java
index 300adbd981..8b7e3604a9 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpReceivingTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpReceivingTransportHandler.java
@@ -25,9 +25,9 @@ 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.SockJsHandler;
-import org.springframework.sockjs.SockJsSessionSupport;
+import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.sockjs.server.TransportHandler;
+import org.springframework.websocket.WebSocketHandler;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -53,7 +53,7 @@ public abstract class AbstractHttpReceivingTransportHandler implements Transport
@Override
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler, SockJsSessionSupport session) throws Exception {
+ WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
if (session == null) {
response.setStatusCode(HttpStatus.NOT_FOUND);
@@ -64,7 +64,7 @@ public abstract class AbstractHttpReceivingTransportHandler implements Transport
}
protected void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
- SockJsSessionSupport session) throws Exception {
+ AbstractSockJsSession session) throws Exception {
String[] messages = null;
try {
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 726fa76c87..978663598c 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
@@ -16,20 +16,19 @@
package org.springframework.sockjs.server.transport;
import java.io.IOException;
-import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.AbstractSockJsSession;
import org.springframework.sockjs.SockJsSessionFactory;
-import org.springframework.sockjs.SockJsSessionSupport;
import org.springframework.sockjs.server.ConfigurableTransportHandler;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
+import org.springframework.websocket.WebSocketHandler;
/**
* TODO
@@ -38,7 +37,7 @@ import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
* @since 4.0
*/
public abstract class AbstractHttpSendingTransportHandler
- implements ConfigurableTransportHandler, SockJsSessionFactory {
+ implements ConfigurableTransportHandler, SockJsSessionFactory {
protected final Log logger = LogFactory.getLog(this.getClass());
@@ -50,18 +49,13 @@ public abstract class AbstractHttpSendingTransportHandler
this.sockJsConfig = sockJsConfig;
}
- @Override
- public void registerSockJsHandlers(Collection sockJsHandlers) {
- // ignore
- }
-
public SockJsConfiguration getSockJsConfig() {
return this.sockJsConfig;
}
@Override
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler, SockJsSessionSupport session) throws Exception {
+ WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
// Set content type before writing
response.getHeaders().setContentType(getContentType());
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpServerSockJsSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpServerSockJsSession.java
index 0c9d624f56..e87006958b 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpServerSockJsSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/AbstractHttpServerSockJsSession.java
@@ -22,7 +22,6 @@ import java.util.concurrent.BlockingQueue;
import org.springframework.http.server.AsyncServerHttpRequest;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.server.AbstractServerSockJsSession;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
@@ -30,6 +29,7 @@ import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportHandler;
import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus;
+import org.springframework.websocket.WebSocketHandler;
/**
* An abstract base class for use with HTTP-based transports.
@@ -48,8 +48,10 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
private ServerHttpResponse response;
- public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, SockJsHandler sockJsHandler) {
- super(sessionId, sockJsConfig, sockJsHandler);
+ public AbstractHttpServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
+ WebSocketHandler webSocketHandler) {
+
+ super(sessionId, sockJsConfig, webSocketHandler);
}
public void setFrameFormat(FrameFormat frameFormat) {
@@ -57,7 +59,7 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
}
public synchronized void setCurrentRequest(ServerHttpRequest request, ServerHttpResponse response,
- FrameFormat frameFormat) throws IOException {
+ FrameFormat frameFormat) throws Exception {
if (isClosed()) {
logger.debug("connection already closed");
@@ -90,14 +92,14 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
return this.response;
}
- protected final synchronized void sendMessageInternal(String message) throws IOException {
+ protected final synchronized void sendMessageInternal(String message) throws Exception {
// assert close() was not called
// threads: TH-Session-Endpoint or any other thread
this.messageCache.add(message);
tryFlushCache();
}
- private void tryFlushCache() throws IOException {
+ private void tryFlushCache() throws Exception {
if (isActive() && !getMessageCache().isEmpty()) {
logger.trace("Flushing messages");
flushCache();
@@ -107,7 +109,7 @@ public abstract class AbstractHttpServerSockJsSession extends AbstractServerSock
/**
* Only called if the connection is currently active
*/
- protected abstract void flushCache() throws IOException;
+ protected abstract void flushCache() throws Exception;
@Override
protected void disconnect(CloseStatus status) {
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 f8dc637c16..0adfd867b1 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
@@ -19,8 +19,8 @@ import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.util.Assert;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -33,9 +33,9 @@ public abstract class AbstractStreamingTransportHandler extends AbstractHttpSend
@Override
- public StreamingServerSockJsSession createSession(String sessionId, SockJsHandler sockJsHandler) {
+ public StreamingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
- return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), sockJsHandler);
+ return new StreamingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
}
@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 23c9f07efb..fabd525393 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
@@ -21,13 +21,13 @@ 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.SockJsHandler;
import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.util.JavaScriptUtils;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -50,9 +50,9 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
}
@Override
- public PollingServerSockJsSession createSession(String sessionId, SockJsHandler sockJsHandler) {
+ public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
- return new PollingServerSockJsSession(sessionId, getSockJsConfig(), sockJsHandler);
+ return new PollingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
}
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpTransportHandler.java
index 95e90dccc0..8d39e2d125 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/JsonpTransportHandler.java
@@ -21,7 +21,7 @@ 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.AbstractSockJsSession;
import org.springframework.sockjs.server.TransportType;
public class JsonpTransportHandler extends AbstractHttpReceivingTransportHandler {
@@ -34,7 +34,7 @@ public class JsonpTransportHandler extends AbstractHttpReceivingTransportHandler
@Override
public void handleRequestInternal(ServerHttpRequest request, ServerHttpResponse response,
- SockJsSessionSupport sockJsSession) throws Exception {
+ AbstractSockJsSession sockJsSession) throws Exception {
if (MediaType.APPLICATION_FORM_URLENCODED.equals(request.getHeaders().getContentType())) {
if (request.getQueryParams().getFirst("d") == null) {
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/PollingServerSockJsSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/PollingServerSockJsSession.java
index baac23d587..c9814f09f2 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/PollingServerSockJsSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/PollingServerSockJsSession.java
@@ -15,21 +15,21 @@
*/
package org.springframework.sockjs.server.transport;
-import java.io.IOException;
-
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
+import org.springframework.websocket.WebSocketHandler;
public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession {
- public PollingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, SockJsHandler sockJsHandler) {
- super(sessionId, sockJsConfig, sockJsHandler);
+ public PollingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
+ WebSocketHandler webSocketHandler) {
+
+ super(sessionId, sockJsConfig, webSocketHandler);
}
@Override
- protected void flushCache() throws IOException {
+ protected void flushCache() throws Exception {
cancelHeartbeat();
String[] messages = getMessageCache().toArray(new String[getMessageCache().size()]);
getMessageCache().clear();
@@ -37,7 +37,7 @@ public class PollingServerSockJsSession extends AbstractHttpServerSockJsSession
}
@Override
- protected void writeFrame(SockJsFrame frame) throws IOException {
+ protected void writeFrame(SockJsFrame frame) throws Exception {
super.writeFrame(frame);
resetRequest();
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/SockJsWebSocketHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/SockJsWebSocketHandler.java
index e616455a2c..4e4dc0987e 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/SockJsWebSocketHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/SockJsWebSocketHandler.java
@@ -22,14 +22,15 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.sockjs.SockJsHandler;
-import org.springframework.sockjs.SockJsSessionSupport;
+import org.springframework.sockjs.AbstractSockJsSession;
import org.springframework.sockjs.server.AbstractServerSockJsSession;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.websocket.CloseStatus;
+import org.springframework.websocket.TextMessage;
+import org.springframework.websocket.TextMessageHandler;
import org.springframework.websocket.WebSocketHandler;
import org.springframework.websocket.WebSocketSession;
@@ -43,55 +44,52 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class SockJsWebSocketHandler implements WebSocketHandler {
+public class SockJsWebSocketHandler implements TextMessageHandler {
private static final Log logger = LogFactory.getLog(SockJsWebSocketHandler.class);
private final SockJsConfiguration sockJsConfig;
- private final SockJsHandler sockJsHandler;
+ private final WebSocketHandler webSocketHandler;
- private final Map sessions =
- new ConcurrentHashMap();
+ private final Map sessions =
+ new ConcurrentHashMap();
// TODO: JSON library used must be configurable
private final ObjectMapper objectMapper = new ObjectMapper();
- public SockJsWebSocketHandler(SockJsConfiguration sockJsConfig, SockJsHandler sockJsHandler) {
+ public SockJsWebSocketHandler(SockJsConfiguration sockJsConfig, WebSocketHandler webSocketHandler) {
Assert.notNull(sockJsConfig, "sockJsConfig is required");
- Assert.notNull(sockJsHandler, "sockJsHandler is required");
+ Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.sockJsConfig = sockJsConfig;
- this.sockJsHandler = sockJsHandler;
+ this.webSocketHandler = webSocketHandler;
}
protected SockJsConfiguration getSockJsConfig() {
return this.sockJsConfig;
}
- protected SockJsHandler getSockJsHandler() {
- return this.sockJsHandler;
- }
-
- protected SockJsSessionSupport getSockJsSession(WebSocketSession wsSession) {
+ protected AbstractSockJsSession getSockJsSession(WebSocketSession wsSession) {
return this.sessions.get(wsSession);
}
@Override
public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
- SockJsSessionSupport session = new WebSocketServerSockJsSession(wsSession, getSockJsConfig());
+ AbstractSockJsSession session = new WebSocketServerSockJsSession(wsSession, getSockJsConfig());
this.sessions.put(wsSession, session);
}
@Override
- public void handleTextMessage(String message, WebSocketSession wsSession) throws Exception {
- if (StringUtils.isEmpty(message)) {
+ public void handleTextMessage(TextMessage message, WebSocketSession wsSession) throws Exception {
+ String payload = message.getPayload();
+ if (StringUtils.isEmpty(payload)) {
logger.trace("Ignoring empty message");
return;
}
try {
- String[] messages = this.objectMapper.readValue(message, String[].class);
- SockJsSessionSupport session = getSockJsSession(wsSession);
+ String[] messages = this.objectMapper.readValue(payload, String[].class);
+ AbstractSockJsSession session = getSockJsSession(wsSession);
session.delegateMessages(messages);
}
catch (IOException e) {
@@ -100,21 +98,15 @@ public class SockJsWebSocketHandler implements WebSocketHandler {
}
}
- @Override
- public void handleBinaryMessage(byte[] message, WebSocketSession session) throws Exception {
- logger.warn("Unexpected binary message for " + session);
- session.close(CloseStatus.NOT_ACCEPTABLE);
- }
-
@Override
public void afterConnectionClosed(CloseStatus status, WebSocketSession wsSession) throws Exception {
- SockJsSessionSupport session = this.sessions.remove(wsSession);
+ AbstractSockJsSession session = this.sessions.remove(wsSession);
session.delegateConnectionClosed(status);
}
@Override
public void handleError(Throwable exception, WebSocketSession webSocketSession) {
- SockJsSessionSupport session = getSockJsSession(webSocketSession);
+ AbstractSockJsSession session = getSockJsSession(webSocketSession);
session.delegateError(exception);
}
@@ -135,9 +127,10 @@ public class SockJsWebSocketHandler implements WebSocketHandler {
public WebSocketServerSockJsSession(WebSocketSession wsSession, SockJsConfiguration sockJsConfig)
throws Exception {
- super(getSockJsSessionId(wsSession), sockJsConfig, getSockJsHandler());
+ super(getSockJsSessionId(wsSession), sockJsConfig, SockJsWebSocketHandler.this.webSocketHandler);
this.wsSession = wsSession;
- this.wsSession.sendTextMessage(SockJsFrame.openFrame().getContent());
+ TextMessage message = new TextMessage(SockJsFrame.openFrame().getContent());
+ this.wsSession.sendMessage(message);
scheduleHeartbeat();
delegateConnectionEstablished();
}
@@ -148,22 +141,23 @@ public class SockJsWebSocketHandler implements WebSocketHandler {
}
@Override
- public void sendMessageInternal(String message) throws IOException {
+ public void sendMessageInternal(String message) throws Exception {
cancelHeartbeat();
writeFrame(SockJsFrame.messageFrame(message));
scheduleHeartbeat();
}
@Override
- protected void writeFrameInternal(SockJsFrame frame) throws IOException {
+ protected void writeFrameInternal(SockJsFrame frame) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Write " + frame);
}
- this.wsSession.sendTextMessage(frame.getContent());
+ TextMessage message = new TextMessage(frame.getContent());
+ this.wsSession.sendMessage(message);
}
@Override
- protected void disconnect(CloseStatus status) throws IOException {
+ protected void disconnect(CloseStatus status) throws Exception {
this.wsSession.close(status);
}
}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingServerSockJsSession.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingServerSockJsSession.java
index e0293a7372..77cacca780 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingServerSockJsSession.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/StreamingServerSockJsSession.java
@@ -18,9 +18,9 @@ package org.springframework.sockjs.server.transport;
import java.io.IOException;
import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.SockJsFrame;
+import org.springframework.websocket.WebSocketHandler;
public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSession {
@@ -28,11 +28,13 @@ public class StreamingServerSockJsSession extends AbstractHttpServerSockJsSessio
private int byteCount;
- public StreamingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig, SockJsHandler sockJsHandler) {
- super(sessionId, sockJsConfig, sockJsHandler);
+ public StreamingServerSockJsSession(String sessionId, SockJsConfiguration sockJsConfig,
+ WebSocketHandler webSocketHandler) {
+
+ super(sessionId, sockJsConfig, webSocketHandler);
}
- protected void flushCache() throws IOException {
+ protected void flushCache() throws Exception {
cancelHeartbeat();
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketSockJsHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketSockJsHandlerAdapter.java
deleted file mode 100644
index 12a5bcd282..0000000000
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/WebSocketSockJsHandlerAdapter.java
+++ /dev/null
@@ -1,132 +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.sockjs.server.transport;
-
-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.sockjs.SockJsHandler;
-import org.springframework.sockjs.SockJsSessionSupport;
-import org.springframework.sockjs.server.SockJsConfiguration;
-import org.springframework.util.Assert;
-import org.springframework.websocket.CloseStatus;
-import org.springframework.websocket.WebSocketHandler;
-import org.springframework.websocket.WebSocketSession;
-
-
-/**
- * A plain {@link WebSocketHandler} to {@link SockJsHandler} adapter that merely delegates
- * without any additional SockJS message framing. Used for raw WebSocket communication at
- * SockJS path "/websocket".
- *
- * @author Rossen Stoyanchev
- * @since 4.0
- */
-public class WebSocketSockJsHandlerAdapter implements WebSocketHandler {
-
- private static final Log logger = LogFactory.getLog(WebSocketSockJsHandlerAdapter.class);
-
- private final SockJsConfiguration sockJsConfig;
-
- private final SockJsHandler sockJsHandler;
-
- private final Map sessions =
- new ConcurrentHashMap();
-
-
- public WebSocketSockJsHandlerAdapter(SockJsConfiguration sockJsConfig, SockJsHandler sockJsHandler) {
- Assert.notNull(sockJsConfig, "sockJsConfig is required");
- Assert.notNull(sockJsHandler, "sockJsHandler is required");
- this.sockJsConfig = sockJsConfig;
- this.sockJsHandler = sockJsHandler;
- }
-
- protected SockJsConfiguration getSockJsConfig() {
- return this.sockJsConfig;
- }
-
- protected SockJsHandler getSockJsHandler() {
- return this.sockJsHandler;
- }
-
- protected SockJsSessionSupport getSockJsSession(WebSocketSession wsSession) {
- return this.sessions.get(wsSession);
- }
-
- @Override
- public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
- SockJsSessionSupport session = new SockJsWebSocketSessionAdapter(wsSession);
- this.sessions.put(wsSession, session);
- }
-
- @Override
- public void handleTextMessage(String message, WebSocketSession wsSession) throws Exception {
- SockJsSessionSupport session = getSockJsSession(wsSession);
- session.delegateMessages(new String[] { message });
- }
-
- @Override
- public void handleBinaryMessage(byte[] message, WebSocketSession session) throws Exception {
- logger.warn("Unexpected binary message for " + session);
- session.close(CloseStatus.NOT_ACCEPTABLE);
- }
-
- @Override
- public void afterConnectionClosed(CloseStatus status, WebSocketSession wsSession) throws Exception {
- SockJsSessionSupport session = this.sessions.remove(wsSession);
- session.delegateConnectionClosed(status);
- }
-
- @Override
- public void handleError(Throwable exception, WebSocketSession wsSession) {
- logger.error("Error for " + wsSession);
- SockJsSessionSupport session = getSockJsSession(wsSession);
- session.delegateError(exception);
- }
-
-
- private class SockJsWebSocketSessionAdapter extends SockJsSessionSupport {
-
- private final WebSocketSession wsSession;
-
-
- public SockJsWebSocketSessionAdapter(WebSocketSession wsSession) throws Exception {
- super(wsSession.getId(), getSockJsHandler());
- this.wsSession = wsSession;
- delegateConnectionEstablished();
- }
-
- @Override
- public boolean isActive() {
- return this.wsSession.isOpen();
- }
-
- @Override
- public void sendMessage(String message) throws IOException {
- this.wsSession.sendTextMessage(message);
- }
-
- @Override
- public void closeInternal(CloseStatus status) throws IOException {
- this.wsSession.close(status);
- }
- }
-
-}
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 32702d00d9..836e7331f5 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
@@ -16,17 +16,9 @@
package org.springframework.sockjs.server.transport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
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.AbstractSockJsSession;
import org.springframework.sockjs.server.ConfigurableTransportHandler;
import org.springframework.sockjs.server.SockJsConfiguration;
import org.springframework.sockjs.server.TransportHandler;
@@ -50,10 +42,6 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
private SockJsConfiguration sockJsConfig;
- private final Map sockJsHandlerCache = new HashMap();
-
- private final Collection rawWebSocketHandlerCache = new ArrayList();
-
public WebSocketTransportHandler(HandshakeHandler handshakeHandler) {
Assert.notNull(handshakeHandler, "handshakeHandler is required");
@@ -71,50 +59,22 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
}
@Override
- public void registerSockJsHandlers(Collection sockJsHandlers) {
- this.sockJsHandlerCache.clear();
- for (SockJsHandler sockJsHandler : sockJsHandlers) {
- this.sockJsHandlerCache.put(sockJsHandler, adaptSockJsHandler(sockJsHandler));
- }
- this.handshakeHandler.registerWebSocketHandlers(getAllWebSocketHandlers());
+ public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
+ WebSocketHandler webSocketHandler, AbstractSockJsSession session) throws Exception {
+
+ this.handshakeHandler.doHandshake(request, response, adaptSockJsHandler(webSocketHandler));
}
/**
* Adapt the {@link SockJsHandler} to the {@link WebSocketHandler} contract for
* exchanging SockJS message over WebSocket.
*/
- protected WebSocketHandler adaptSockJsHandler(SockJsHandler sockJsHandler) {
- return new SockJsWebSocketHandler(this.sockJsConfig, sockJsHandler);
- }
-
- private Collection getAllWebSocketHandlers() {
- Set handlers = new HashSet();
- handlers.addAll(this.sockJsHandlerCache.values());
- handlers.addAll(this.rawWebSocketHandlerCache);
- return handlers;
- }
-
- @Override
- public void handleRequest(ServerHttpRequest request, ServerHttpResponse response,
- SockJsHandler sockJsHandler, SockJsSessionSupport session) throws Exception {
-
- WebSocketHandler webSocketHandler = this.sockJsHandlerCache.get(sockJsHandler);
- if (webSocketHandler == null) {
- webSocketHandler = adaptSockJsHandler(sockJsHandler);
- }
-
- this.handshakeHandler.doHandshake(request, response, webSocketHandler);
+ protected WebSocketHandler adaptSockJsHandler(WebSocketHandler handler) {
+ return new SockJsWebSocketHandler(this.sockJsConfig, handler);
}
// HandshakeHandler methods
- @Override
- public void registerWebSocketHandlers(Collection webSocketHandlers) {
- this.rawWebSocketHandlerCache.clear();
- this.rawWebSocketHandlerCache.addAll(webSocketHandlers);
- this.handshakeHandler.registerWebSocketHandlers(getAllWebSocketHandlers());
- }
-
@Override
public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler webSocketHandler) throws Exception {
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/XhrPollingTransportHandler.java b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/XhrPollingTransportHandler.java
index e424bac91a..57b5fd4e94 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/XhrPollingTransportHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/sockjs/server/transport/XhrPollingTransportHandler.java
@@ -19,11 +19,11 @@ import java.nio.charset.Charset;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.sockjs.SockJsHandler;
import org.springframework.sockjs.server.SockJsFrame.DefaultFrameFormat;
import org.springframework.sockjs.server.SockJsFrame.FrameFormat;
import org.springframework.sockjs.server.TransportType;
import org.springframework.util.Assert;
+import org.springframework.websocket.WebSocketHandler;
/**
@@ -50,9 +50,9 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
return new DefaultFrameFormat("%s\n");
}
- public PollingServerSockJsSession createSession(String sessionId, SockJsHandler sockJsHandler) {
+ public PollingServerSockJsSession createSession(String sessionId, WebSocketHandler webSocketHandler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
- return new PollingServerSockJsSession(sessionId, getSockJsConfig(), sockJsHandler);
+ return new PollingServerSockJsSession(sessionId, getSockJsConfig(), webSocketHandler);
}
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/BinaryMessage.java b/spring-websocket/src/main/java/org/springframework/websocket/BinaryMessage.java
new file mode 100644
index 0000000000..5f136bc31e
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/websocket/BinaryMessage.java
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+
+/**
+ * Represents a binary WebSocket message.
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ */
+public final class BinaryMessage extends WebSocketMessage {
+
+ private final byte[] bytes;
+
+ private final boolean last;
+
+
+ public BinaryMessage(ByteBuffer payload) {
+ this(payload, true);
+ }
+
+ public BinaryMessage(ByteBuffer payload, boolean isLast) {
+ super(payload);
+ this.bytes = null;
+ this.last = isLast;
+ }
+
+ public BinaryMessage(byte[] payload) {
+ this(payload, true);
+ }
+
+ public BinaryMessage(byte[] payload, boolean isLast) {
+ super((payload != null) ? ByteBuffer.wrap(payload) : null);
+ this.bytes = payload;
+ this.last = isLast;
+ }
+
+ public boolean isLast() {
+ return this.last;
+ }
+
+ public byte[] getByteArray() {
+ if (this.bytes != null) {
+ return this.bytes;
+ }
+ else if (getPayload() != null){
+ byte[] result = new byte[getPayload().remaining()];
+ getPayload().get(result);
+ return result;
+ }
+ else {
+ return null;
+ }
+ }
+
+ public InputStream getInputStream() {
+ byte[] array = getByteArray();
+ return (array != null) ? new ByteArrayInputStream(array) : null;
+ }
+
+ @Override
+ public String toString() {
+ int size = (getPayload() != null) ? getPayload().remaining() : 0;
+ return "WebSocket binary message size=" + size;
+ }
+
+}
diff --git a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/websocket/BinaryMessageHandler.java
similarity index 52%
rename from spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandlerAdapter.java
rename to spring-websocket/src/main/java/org/springframework/websocket/BinaryMessageHandler.java
index 3523f6c0dc..50940e34da 100644
--- a/spring-websocket/src/main/java/org/springframework/sockjs/SockJsHandlerAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/BinaryMessageHandler.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -13,33 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.springframework.websocket;
-package org.springframework.sockjs;
-
-import org.springframework.websocket.CloseStatus;
/**
+ * A handler for WebSocket binary messages.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class SockJsHandlerAdapter implements SockJsHandler {
+public interface BinaryMessageHandler extends WebSocketHandler {
- @Override
- public void afterConnectionEstablished(SockJsSession session) throws Exception {
- }
- @Override
- public void handleMessage(String message, SockJsSession session) throws Exception {
- }
-
- @Override
- public void handleError(Throwable exception, SockJsSession session) {
- }
-
- @Override
- public void afterConnectionClosed(CloseStatus status, SockJsSession session) {
- }
+ /**
+ * Handle an incoming binary message.
+ */
+ void handleBinaryMessage(BinaryMessage message, WebSocketSession session)
+ throws Exception;
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/PartialMessageHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/PartialMessageHandler.java
new file mode 100644
index 0000000000..7752baf6cc
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/websocket/PartialMessageHandler.java
@@ -0,0 +1,28 @@
+/*
+ * 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 "marker" interface for {@link BinaryMessageHandler} types that wish to handle partial
+ * messages.
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ */
+public interface PartialMessageHandler {
+
+}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandshakeRequest.java b/spring-websocket/src/main/java/org/springframework/websocket/TextMessage.java
similarity index 63%
rename from spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandshakeRequest.java
rename to spring-websocket/src/main/java/org/springframework/websocket/TextMessage.java
index 762cc2fe8b..b254ae7f80 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandshakeRequest.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/TextMessage.java
@@ -15,34 +15,25 @@
*/
package org.springframework.websocket;
-import java.net.URI;
-
-import org.springframework.http.HttpHeaders;
+import java.io.Reader;
+import java.io.StringReader;
/**
+ * Represents a text WebSocket message.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
-public class WebSocketHandshakeRequest {
-
- private final URI uri;
-
- private final HttpHeaders headers;
+public final class TextMessage extends WebSocketMessage {
- public WebSocketHandshakeRequest(HttpHeaders headers, URI uri) {
- this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
- this.uri = uri;
+ public TextMessage(String payload) {
+ super(payload);
}
- public URI getUri() {
- return this.uri;
- }
-
- public HttpHeaders getHeaders() {
- return this.headers;
+ public Reader getReader() {
+ return new StringReader(getPayload());
}
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/TextMessageHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/TextMessageHandler.java
new file mode 100644
index 0000000000..ea073eaf3d
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/websocket/TextMessageHandler.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import org.springframework.websocket.WebSocketHandlerAdapter.TextAndBinaryMessageHandlerAdapter;
+import org.springframework.websocket.WebSocketHandlerAdapter.TextMessageHandlerAdapter;
+
+
+/**
+ * A handler for WebSocket text messages.
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ *
+ * @see TextMessageHandlerAdapter
+ * @see TextAndBinaryMessageHandlerAdapter
+ */
+public interface TextMessageHandler extends WebSocketHandler {
+
+
+ /**
+ * Handle an incoming text message.
+ */
+ void handleTextMessage(TextMessage message, WebSocketSession session)
+ throws Exception;
+
+}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandler.java
index 783e9b66d1..b420e83940 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandler.java
@@ -19,7 +19,7 @@ package org.springframework.websocket;
/**
- * A handler for WebSocket messages.
+ * A handler for WebSocket sessions.
*
* @author Rossen Stoyanchev
* @since 4.0
@@ -32,23 +32,13 @@ public interface WebSocketHandler {
void afterConnectionEstablished(WebSocketSession session) throws Exception;
/**
- * Handle an incoming text message.
+ * A WebSocket connection has been closed.
*/
- void handleTextMessage(String message, WebSocketSession session) throws Exception;
-
- /**
- * Handle an incoming binary message.
- */
- void handleBinaryMessage(byte[] bytes, WebSocketSession session) throws Exception;
+ void afterConnectionClosed(CloseStatus closeStatus, WebSocketSession session) throws Exception;
/**
* TODO
*/
void handleError(Throwable exception, WebSocketSession session);
- /**
- * A WebSocket connection has been closed.
- */
- void afterConnectionClosed(CloseStatus closeStatus, WebSocketSession session) throws Exception;
-
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandlerAdapter.java
index af03f63b1c..4914f3767a 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandlerAdapter.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketHandlerAdapter.java
@@ -18,6 +18,7 @@ package org.springframework.websocket;
/**
+ * A {@link WebSocketHandler} with empty methods.
*
* @author Rossen Stoyanchev
* @since 4.0
@@ -29,19 +30,24 @@ public class WebSocketHandlerAdapter implements WebSocketHandler {
}
@Override
- public void handleTextMessage(String message, WebSocketSession session) throws Exception {
- }
-
- @Override
- public void handleBinaryMessage(byte[] message, WebSocketSession session) throws Exception {
+ public void afterConnectionClosed(CloseStatus status, WebSocketSession session) throws Exception {
}
@Override
public void handleError(Throwable exception, WebSocketSession session) {
}
- @Override
- public void afterConnectionClosed(CloseStatus status, WebSocketSession session) throws Exception {
+
+ public static abstract class TextMessageHandlerAdapter
+ extends WebSocketHandlerAdapter implements TextMessageHandler {
+ }
+
+ public static abstract class BinaryMessageHandlerAdapter
+ extends WebSocketHandlerAdapter implements BinaryMessageHandler {
+ }
+
+ public static abstract class TextAndBinaryMessageHandlerAdapter extends WebSocketHandlerAdapter
+ implements TextMessageHandler, BinaryMessageHandler {
}
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketMessage.java b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketMessage.java
new file mode 100644
index 0000000000..19b79eda74
--- /dev/null
+++ b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketMessage.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import org.springframework.util.ObjectUtils;
+
+
+/**
+ *
+ * @author Rossen Stoyanchev
+ * @since 4.0
+ */
+public abstract class WebSocketMessage {
+
+ private final T payload;
+
+
+ WebSocketMessage(T payload) {
+ this.payload = payload;
+ }
+
+ public T getPayload() {
+ return this.payload;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " [payload=" + this.payload + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ return WebSocketMessage.class.hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.payload);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof WebSocketMessage)) {
+ return false;
+ }
+ WebSocketMessage otherMessage = (WebSocketMessage) other;
+ return ObjectUtils.nullSafeEquals(this.payload, otherMessage.payload);
+ }
+
+}
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 d1d3c27a35..2c9d4355f5 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/WebSocketSession.java
@@ -16,9 +16,7 @@
package org.springframework.websocket;
-import java.io.IOException;
import java.net.URI;
-import java.nio.ByteBuffer;
@@ -51,14 +49,10 @@ public interface WebSocketSession {
URI getURI();
/**
- * Send a text message.
+ * Send a WebSocket message either {@link TextMessage} or
+ * {@link BinaryMessage}.
*/
- void sendTextMessage(String message) throws IOException;
-
- /**
- * Send a binary message.
- */
- void sendBinaryMessage(ByteBuffer message) throws IOException;
+ void sendMessage(WebSocketMessage message) throws Exception;
/**
* Close the WebSocket connection with status 1000, i.e. equivalent to:
@@ -66,11 +60,11 @@ public interface WebSocketSession {
* session.close(CloseStatus.NORMAL);
*
*/
- void close() throws IOException;
+ void close() throws Exception;
/**
* Close the WebSocket connection with the given close status.
*/
- void close(CloseStatus status) throws IOException;
+ void close(CloseStatus status) throws Exception;
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
index 64f4d4d7fd..0da50203ee 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/StandardWebSocketSession.java
@@ -18,15 +18,18 @@ package org.springframework.websocket.endpoint;
import java.io.IOException;
import java.net.URI;
-import java.nio.ByteBuffer;
import javax.websocket.CloseReason;
import javax.websocket.CloseReason.CloseCodes;
+import javax.websocket.RemoteEndpoint.Basic;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
+import org.springframework.websocket.BinaryMessage;
import org.springframework.websocket.CloseStatus;
+import org.springframework.websocket.TextMessage;
+import org.springframework.websocket.WebSocketMessage;
import org.springframework.websocket.WebSocketSession;
@@ -70,21 +73,21 @@ public class StandardWebSocketSession implements WebSocketSession {
}
@Override
- public void sendTextMessage(String text) throws IOException {
+ public void sendMessage(WebSocketMessage message) throws IOException {
if (logger.isTraceEnabled()) {
- logger.trace("Sending text message: " + text + ", " + this);
+ logger.trace("Sending: " + message + ", " + this);
}
Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
- this.session.getBasicRemote().sendText(text);
- }
-
- @Override
- public void sendBinaryMessage(ByteBuffer message) throws IOException {
- if (logger.isTraceEnabled()) {
- logger.trace("Sending binary message, " + this);
+ Basic remote = this.session.getBasicRemote();
+ if (message instanceof TextMessage) {
+ remote.sendText(((TextMessage) message).getPayload());
+ }
+ else if (message instanceof BinaryMessage) {
+ remote.sendBinary(((BinaryMessage) message).getPayload());
+ }
+ else {
+ throw new IllegalStateException("Unexpected WebSocketMessage type: " + message);
}
- Assert.isTrue(isOpen(), "Cannot send message after connection closed.");
- this.session.getBasicRemote().sendBinary(message);
}
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
index 7593adbfd0..82d75c098d 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/endpoint/WebSocketHandlerEndpoint.java
@@ -28,8 +28,13 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.websocket.CloseStatus;
-import org.springframework.websocket.WebSocketSession;
+import org.springframework.websocket.BinaryMessage;
+import org.springframework.websocket.BinaryMessageHandler;
+import org.springframework.websocket.PartialMessageHandler;
import org.springframework.websocket.WebSocketHandler;
+import org.springframework.websocket.WebSocketSession;
+import org.springframework.websocket.TextMessage;
+import org.springframework.websocket.TextMessageHandler;
/**
@@ -47,19 +52,50 @@ public class WebSocketHandlerEndpoint extends Endpoint {
private final Map sessions = new ConcurrentHashMap();
- public WebSocketHandlerEndpoint(WebSocketHandler webSocketHandler) {
- this.webSocketHandler = webSocketHandler;
+ public WebSocketHandlerEndpoint(WebSocketHandler handler) {
+ Assert.notNull(handler, "webSocketHandler is required");
+ this.webSocketHandler = handler;
}
@Override
- public void onOpen(javax.websocket.Session session, EndpointConfig config) {
+ public void onOpen(final javax.websocket.Session session, EndpointConfig config) {
if (logger.isDebugEnabled()) {
logger.debug("Client connected, WebSocket session id=" + session.getId() + ", uri=" + session.getRequestURI());
}
try {
WebSocketSession webSocketSession = new StandardWebSocketSession(session);
this.sessions.put(session.getId(), webSocketSession);
- session.addMessageHandler(new StandardMessageHandler(session));
+
+ if (this.webSocketHandler instanceof TextMessageHandler) {
+ session.addMessageHandler(new MessageHandler.Whole() {
+ @Override
+ public void onMessage(String message) {
+ handleTextMessage(session, message);
+ }
+ });
+ }
+ else if (this.webSocketHandler instanceof BinaryMessageHandler) {
+ if (this.webSocketHandler instanceof PartialMessageHandler) {
+ session.addMessageHandler(new MessageHandler.Partial() {
+ @Override
+ public void onMessage(byte[] messagePart, boolean isLast) {
+ handleBinaryMessage(session, messagePart, isLast);
+ }
+ });
+ }
+ else {
+ session.addMessageHandler(new MessageHandler.Whole() {
+ @Override
+ public void onMessage(byte[] message) {
+ handleBinaryMessage(session, message, true);
+ }
+ });
+ }
+ }
+ else {
+ logger.warn("WebSocketHandler handles neither text nor binary messages: " + this.webSocketHandler);
+ }
+
this.webSocketHandler.afterConnectionEstablished(webSocketSession);
}
catch (Throwable ex) {
@@ -68,6 +104,38 @@ public class WebSocketHandlerEndpoint extends Endpoint {
}
}
+ private void handleTextMessage(javax.websocket.Session session, String message) {
+ if (logger.isTraceEnabled()) {
+ logger.trace("Received message for WebSocket session id=" + session.getId() + ": " + message);
+ }
+ WebSocketSession wsSession = getWebSocketSession(session);
+ Assert.notNull(wsSession, "WebSocketSession not found");
+ try {
+ TextMessage textMessage = new TextMessage(message);
+ ((TextMessageHandler) webSocketHandler).handleTextMessage(textMessage, wsSession);
+ }
+ catch (Throwable ex) {
+ // TODO
+ logger.error("Error while processing message", ex);
+ }
+ }
+
+ private void handleBinaryMessage(javax.websocket.Session session, byte[] message, boolean isLast) {
+ if (logger.isTraceEnabled()) {
+ logger.trace("Received binary data for WebSocket session id=" + session.getId());
+ }
+ WebSocketSession wsSession = getWebSocketSession(session);
+ Assert.notNull(wsSession, "WebSocketSession not found");
+ try {
+ BinaryMessage binaryMessage = new BinaryMessage(message, isLast);
+ ((BinaryMessageHandler) webSocketHandler).handleBinaryMessage(binaryMessage, wsSession);
+ }
+ catch (Throwable ex) {
+ // TODO
+ logger.error("Error while processing message", ex);
+ }
+ }
+
@Override
public void onClose(javax.websocket.Session session, CloseReason reason) {
if (logger.isDebugEnabled()) {
@@ -111,31 +179,4 @@ public class WebSocketHandlerEndpoint extends Endpoint {
return this.sessions.get(session.getId());
}
-
- private class StandardMessageHandler implements MessageHandler.Whole {
-
- private final javax.websocket.Session session;
-
- public StandardMessageHandler(javax.websocket.Session session) {
- this.session = session;
- }
-
- @Override
- public void onMessage(String message) {
- if (logger.isTraceEnabled()) {
- logger.trace("Received message for WebSocket session id=" + this.session.getId() + ": " + message);
- }
- WebSocketSession wsSession = getWebSocketSession(this.session);
- Assert.notNull(wsSession, "WebSocketSession not found");
- try {
- WebSocketHandlerEndpoint.this.webSocketHandler.handleTextMessage(message, wsSession);
- }
- catch (Throwable ex) {
- // TODO
- logger.error("Error while processing message", ex);
- }
- }
-
- }
-
}
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/DefaultHandshakeHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/server/DefaultHandshakeHandler.java
index cf4e4046f6..c7a3fdcb87 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/DefaultHandshakeHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/DefaultHandshakeHandler.java
@@ -21,7 +21,6 @@ import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -86,11 +85,6 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
return this.supportedProtocols.toArray(new String[this.supportedProtocols.size()]);
}
- @Override
- public void registerWebSocketHandlers(Collection handlers) {
- this.requestUpgradeStrategy.registerWebSocketHandlers(handlers);
- }
-
@Override
public final boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler webSocketHandler) throws Exception {
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/HandshakeHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/server/HandshakeHandler.java
index 8222e7258e..2af525c606 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/HandshakeHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/HandshakeHandler.java
@@ -16,8 +16,6 @@
package org.springframework.websocket.server;
-import java.util.Collection;
-
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.WebSocketHandler;
@@ -31,14 +29,6 @@ import org.springframework.websocket.WebSocketHandler;
*/
public interface HandshakeHandler {
- /**
- * Pre-register {@link WebSocketHandler} instances so they can be adapted to the
- * underlying runtime and hence re-used at runtime when
- * {@link #doHandshake(ServerHttpRequest, ServerHttpResponse, WebSocketHandler) doHandshake}
- * is called.
- */
- void registerWebSocketHandlers(Collection webSocketHandlers);
-
/**
*
* @param request the HTTP request
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/RequestUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/websocket/server/RequestUpgradeStrategy.java
index d0cf29fa17..81c238c423 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/RequestUpgradeStrategy.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/RequestUpgradeStrategy.java
@@ -16,8 +16,6 @@
package org.springframework.websocket.server;
-import java.util.Collection;
-
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.websocket.WebSocketHandler;
@@ -37,14 +35,6 @@ public interface RequestUpgradeStrategy {
*/
String[] getSupportedVersions();
- /**
- * Pre-register {@link WebSocketHandler} instances so they can be adapted to the
- * underlying runtime and hence re-used at runtime when
- * {@link #upgrade(ServerHttpRequest, ServerHttpResponse, String, WebSocketHandler)
- * upgrade} is called.
- */
- void registerWebSocketHandlers(Collection webSocketHandlers);
-
/**
* Perform runtime specific steps to complete the upgrade.
* Invoked only if the handshake is successful.
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/support/AbstractEndpointUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/websocket/server/support/AbstractEndpointUpgradeStrategy.java
index 29b2372f91..b16f3d746d 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/support/AbstractEndpointUpgradeStrategy.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/support/AbstractEndpointUpgradeStrategy.java
@@ -16,10 +16,6 @@
package org.springframework.websocket.server.support;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
import javax.websocket.Endpoint;
import org.apache.commons.logging.Log;
@@ -42,38 +38,18 @@ public abstract class AbstractEndpointUpgradeStrategy implements RequestUpgradeS
protected final Log logger = LogFactory.getLog(getClass());
- private final Map webSocketHandlers = new HashMap();
-
@Override
- public void registerWebSocketHandlers(Collection webSocketHandlers) {
- for (WebSocketHandler webSocketHandler : webSocketHandlers) {
- if (!this.webSocketHandlers.containsKey(webSocketHandler)) {
- this.webSocketHandlers.put(webSocketHandler, adaptWebSocketHandler(webSocketHandler));
- }
- }
+ public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
+ String protocol, WebSocketHandler webSocketHandler) throws Exception {
+
+ upgradeInternal(request, response, protocol, adaptWebSocketHandler(webSocketHandler));
}
protected Endpoint adaptWebSocketHandler(WebSocketHandler handler) {
return new WebSocketHandlerEndpoint(handler);
}
- @Override
- public void upgrade(ServerHttpRequest request, ServerHttpResponse response,
- String protocol, WebSocketHandler webSocketHandler) throws Exception {
-
- Endpoint endpoint = this.webSocketHandlers.get(webSocketHandler);
- if (endpoint == null) {
- endpoint = adaptWebSocketHandler(webSocketHandler);
- }
-
- if (logger.isTraceEnabled()) {
- logger.trace("Upgrading with " + endpoint);
- }
-
- upgradeInternal(request, response, protocol, endpoint);
- }
-
protected abstract void upgradeInternal(ServerHttpRequest request, ServerHttpResponse response,
String selectedProtocol, Endpoint endpoint) throws Exception;
diff --git a/spring-websocket/src/main/java/org/springframework/websocket/server/support/WebSocketHttpRequestHandler.java b/spring-websocket/src/main/java/org/springframework/websocket/server/support/WebSocketHttpRequestHandler.java
index 6e641eaba0..9418afc689 100644
--- a/spring-websocket/src/main/java/org/springframework/websocket/server/support/WebSocketHttpRequestHandler.java
+++ b/spring-websocket/src/main/java/org/springframework/websocket/server/support/WebSocketHttpRequestHandler.java
@@ -17,7 +17,6 @@
package org.springframework.websocket.server.support;
import java.io.IOException;
-import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -35,8 +34,8 @@ import org.springframework.web.HttpRequestHandler;
import org.springframework.web.util.NestedServletException;
import org.springframework.websocket.HandlerProvider;
import org.springframework.websocket.WebSocketHandler;
-import org.springframework.websocket.server.HandshakeHandler;
import org.springframework.websocket.server.DefaultHandshakeHandler;
+import org.springframework.websocket.server.HandshakeHandler;
/**
@@ -56,7 +55,6 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFact
Assert.notNull(webSocketHandler, "webSocketHandler is required");
this.handlerProvider = new HandlerProvider(webSocketHandler);
this.handshakeHandler = new DefaultHandshakeHandler();
- this.handshakeHandler.registerWebSocketHandlers(Collections.singleton(webSocketHandler));
}
public WebSocketHttpRequestHandler( Class extends WebSocketHandler> webSocketHandlerClass) {
@@ -67,9 +65,6 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, BeanFact
public void setHandshakeHandler(HandshakeHandler handshakeHandler) {
Assert.notNull(handshakeHandler, "handshakeHandler is required");
this.handshakeHandler = handshakeHandler;
- if (this.handlerProvider.isSingleton()) {
- this.handshakeHandler.registerWebSocketHandlers(Collections.singleton(this.handlerProvider.getHandler()));
- }
}
@Override