From 164a9f938ccef29923476a4cf50565d4fa54d528 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 29 Aug 2013 17:12:31 -0400 Subject: [PATCH] Update the Jetty WebSocket adapter This changes switches from using Jetty's WebSocketListener interface to use Jetty's @WebSocket annotations instead. The change should be transparent but the annnotations provide a little more controler including handling pong frames. This change also introduces a WebSocketMessage interface. Issue: SPR-10877 --- .../support/MessageHandlingException.java | 2 + .../simp/BrokerAvailabilityEvent.java | 3 + .../web/socket/AbstractWebSocketMessage.java | 101 ++++++++++++++++++ .../web/socket/BinaryMessage.java | 76 ++++++------- .../web/socket/PingMessage.java | 19 +++- .../web/socket/PongMessage.java | 15 ++- .../web/socket/ReaderTextMessage.java | 55 ---------- .../web/socket/TextMessage.java | 16 ++- .../web/socket/WebSocketHandler.java | 12 ++- .../web/socket/WebSocketMessage.java | 68 ++---------- .../adapter/AbstractWebSocketSesssion.java | 2 - .../adapter/JettyWebSocketHandlerAdapter.java | 45 ++++++-- .../socket/support/WebSocketHttpHeaders.java | 2 + .../config/WebSocketConfigurationTests.java | 8 +- 14 files changed, 238 insertions(+), 186 deletions(-) create mode 100644 spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java delete mode 100644 spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java index b3de5cb9ad..c2f07a91bd 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java @@ -28,6 +28,8 @@ import org.springframework.messaging.MessagingException; */ public class MessageHandlingException extends MessagingException { + private static final long serialVersionUID = 690969923668400297L; + public MessageHandlingException(Message message, String description, Throwable cause) { super(message, description, cause); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java index 119021a883..ce418eee3b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java @@ -26,8 +26,11 @@ import org.springframework.context.ApplicationEvent; */ public class BrokerAvailabilityEvent extends ApplicationEvent { + private static final long serialVersionUID = -8156742505179181002L; + private final boolean brokerAvailable; + /** * Creates a new {@code BrokerAvailabilityEvent}. * diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java new file mode 100644 index 0000000000..12a9f7752e --- /dev/null +++ b/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java @@ -0,0 +1,101 @@ +/* + * 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.web.socket; + +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; + +/** + * A message that can be handled or sent on a WebSocket connection. + * + * @author Rossen Stoyanchev + * @since 4.0 + */ +public abstract class AbstractWebSocketMessage implements WebSocketMessage { + + private final T payload; + + private final boolean last; + + + /** + * Create a new WebSocket message with the given payload. + * + * @param payload the non-null payload + */ + AbstractWebSocketMessage(T payload) { + this(payload, true); + } + + /** + * Create a new WebSocket message given payload representing the full or partial + * message content. When the {@code isLast} boolean flag is set to {@code false} + * the message is sent as partial content and more partial messages will be + * expected until the boolean flag is set to {@code true}. + * + * @param payload the non-null payload + * @param isLast if the message is the last of a series of partial messages + */ + AbstractWebSocketMessage(T payload, boolean isLast) { + Assert.notNull(payload, "payload is required"); + this.payload = payload; + this.last = isLast; + } + + + /** + * Return the message payload, never be {@code null}. + */ + public T getPayload() { + return this.payload; + } + + /** + * Whether this is the last part of a message sent as a series of partial messages. + */ + public boolean isLast() { + return this.last; + } + + @Override + public int hashCode() { + return AbstractWebSocketMessage.class.hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.payload); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof AbstractWebSocketMessage)) { + return false; + } + AbstractWebSocketMessage otherMessage = (AbstractWebSocketMessage) other; + return ObjectUtils.nullSafeEquals(this.payload, otherMessage.payload); + } + + @Override + public String toString() { + return getClass().getSimpleName() + " payload= " + toStringPayload() + + ", length=" + getPayloadSize() + ", last=" + isLast() + "]"; + } + + protected abstract String toStringPayload(); + + protected abstract int getPayloadSize(); + +} diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java index d42d3da865..a95f05332c 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java @@ -19,92 +19,82 @@ package org.springframework.web.socket; import java.nio.ByteBuffer; /** - * A {@link WebSocketMessage} that contains a binary {@link ByteBuffer} payload. + * A binary WebSocket message. * * @author Rossen Stoyanchev * @since 4.0 */ -public final class BinaryMessage extends WebSocketMessage { - - private byte[] bytes; +public final class BinaryMessage extends AbstractWebSocketMessage { /** - * Create a new {@link BinaryMessage} instance. + * Create a new binary WebSocket message with the given ByteBuffer payload. + * * @param payload the non-null payload */ public BinaryMessage(ByteBuffer payload) { - this(payload, true); + super(payload, true); } /** - * Create a new {@link BinaryMessage} instance. + * Create a new binary WebSocket message with the given payload representing the + * full or partial message content. When the {@code isLast} boolean flag is set + * to {@code false} the message is sent as partial content and more partial + * messages will be expected until the boolean flag is set to {@code true}. + * * @param payload the non-null payload * @param isLast if the message is the last of a series of partial messages */ public BinaryMessage(ByteBuffer payload, boolean isLast) { super(payload, isLast); - this.bytes = null; } /** - * Create a new {@link BinaryMessage} instance. - * @param payload the non-null payload + * Create a new binary WebSocket message with the given byte[] payload. + * + * @param payload a non-null payload; note that this value is not copied so care + * must be taken not to modify the array. */ public BinaryMessage(byte[] payload) { - this(payload, 0, (payload == null ? 0 : payload.length), true); + this(payload, true); } /** - * Create a new {@link BinaryMessage} instance. - * @param payload the non-null payload + * Create a new binary WebSocket message with the given byte[] payload representing + * the full or partial message content. When the {@code isLast} boolean flag is set + * to {@code false} the message is sent as partial content and more partial + * messages will be expected until the boolean flag is set to {@code true}. + * + * @param payload a non-null payload; note that this value is not copied so care + * must be taken not to modify the array. * @param isLast if the message is the last of a series of partial messages */ public BinaryMessage(byte[] payload, boolean isLast) { - this(payload, 0, (payload == null ? 0 : payload.length), isLast); + this(payload, 0, ((payload == null) ? 0 : payload.length), isLast); } /** - * Create a new {@link BinaryMessage} instance by wrapping an existing byte array. - * @param payload a non-null payload, NOTE: this value is not copied so care must be - * taken not to modify the array. - * @param offset the offet into the array where the payload starts - * @param len the length of the array considered for the payload + * Create a new binary WebSocket message by wrapping an existing byte array. + * + * @param payload a non-null payload; note that this value is not copied so care + * must be taken not to modify the array. + * @param offset the offset into the array where the payload starts + * @param length the length of the array considered for the payload * @param isLast if the message is the last of a series of partial messages */ - public BinaryMessage(byte[] payload, int offset, int len, boolean isLast) { - super(payload != null ? ByteBuffer.wrap(payload, offset, len) : null, isLast); - if(offset == 0 && len == payload.length) { - this.bytes = payload; - } + public BinaryMessage(byte[] payload, int offset, int length, boolean isLast) { + super((payload != null) ? ByteBuffer.wrap(payload, offset, length) : null, isLast); } - /** - * Returns access to the message payload as a byte array. NOTE: the returned array - * should be considered read-only and should not be modified. - */ - public byte[] getByteArray() { - if(this.bytes == null && getPayload() != null) { - this.bytes = getRemainingBytes(getPayload()); - } - return this.bytes; - } - - private byte[] getRemainingBytes(ByteBuffer payload) { - byte[] result = new byte[getPayload().remaining()]; - getPayload().get(result); - return result; - } - @Override protected int getPayloadSize() { - return (getPayload() != null) ? getPayload().remaining() : 0; + return getPayload().remaining(); } @Override protected String toStringPayload() { - return (getPayload() != null) ? getPayload().toString() : null; + return getPayload().toString(); } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java index deea0f7dcc..cf07739e66 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java @@ -24,21 +24,34 @@ import java.nio.ByteBuffer; * @author Rossen Stoyanchev * @since 4.0 */ -public final class PingMessage extends WebSocketMessage { +public final class PingMessage extends AbstractWebSocketMessage { + /** + * Create a new ping message with an empty payload. + */ + public PingMessage() { + super(ByteBuffer.allocate(0)); + } + + /** + * Create a new ping message with the given ByteBuffer payload. + * + * @param payload the non-null payload + */ public PingMessage(ByteBuffer payload) { super(payload); } + @Override protected int getPayloadSize() { - return (getPayload() != null) ? getPayload().remaining() : 0; + return getPayload().remaining(); } @Override protected String toStringPayload() { - return (getPayload() != null) ? getPayload().toString() : null; + return getPayload().toString(); } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java index 42f816c3c5..1d94edd815 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java @@ -24,13 +24,26 @@ import java.nio.ByteBuffer; * @author Rossen Stoyanchev * @since 4.0 */ -public final class PongMessage extends WebSocketMessage { +public final class PongMessage extends AbstractWebSocketMessage { + /** + * Create a new pong message with an empty payload. + */ + public PongMessage() { + super(ByteBuffer.allocate(0)); + } + + /** + * Create a new pong message with the given ByteBuffer payload. + * + * @param payload the non-null payload + */ public PongMessage(ByteBuffer payload) { super(payload); } + @Override protected int getPayloadSize() { return (getPayload() != null) ? getPayload().remaining() : 0; diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java deleted file mode 100644 index 25f4521740..0000000000 --- a/spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java +++ /dev/null @@ -1,55 +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.web.socket; - -/** - * A {@link WebSocketMessage} that contains a textual {@link String} payload. - * - * @author Rossen Stoyanchev - * @since 4.0 - */ -public final class ReaderTextMessage extends WebSocketMessage { - - /** - * Create a new {@link ReaderTextMessage} instance. - * @param payload the non-null payload - */ - public ReaderTextMessage(CharSequence payload) { - super(payload.toString(), true); - } - - /** - * Create a new {@link ReaderTextMessage} instance. - * @param payload the non-null payload - * @param isLast whether this the last part of a message received or transmitted in parts - */ - public ReaderTextMessage(CharSequence payload, boolean isLast) { - super(payload.toString(), isLast); - } - - - @Override - protected int getPayloadSize() { - return getPayload().length(); - } - - @Override - protected String toStringPayload() { - return (getPayloadSize() > 10) ? getPayload().substring(0, 10) + ".." : getPayload(); - } - -} diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java index fb9c4c8412..f4c354b9b0 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java @@ -17,15 +17,17 @@ package org.springframework.web.socket; /** - * A {@link WebSocketMessage} that contains a textual {@link String} payload. + * A text WebSocket message. * * @author Rossen Stoyanchev * @since 4.0 */ -public final class TextMessage extends WebSocketMessage { +public final class TextMessage extends AbstractWebSocketMessage { + /** - * Create a new {@link TextMessage} instance. + * Create a new text WebSocket message from the given CharSequence payload. + * * @param payload the non-null payload */ public TextMessage(CharSequence payload) { @@ -33,9 +35,13 @@ public final class TextMessage extends WebSocketMessage { } /** - * Create a new {@link TextMessage} instance. + * Create a new text WebSocket message with the given payload representing the + * full or partial message content. When the {@code isLast} boolean flag is set + * to {@code false} the message is sent as partial content and more partial + * messages will be expected until the boolean flag is set to {@code true}. + * * @param payload the non-null payload - * @param isLast whether this the last part of a message received or transmitted in parts + * @param isLast whether this the last part of a series of partial messages */ public TextMessage(CharSequence payload, boolean isLast) { super(payload.toString(), isLast); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java index 07f5499f2c..f5c2960eb2 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java @@ -18,8 +18,8 @@ package org.springframework.web.socket; /** * A handler for WebSocket messages and lifecycle events. - * - *

Implementations of this interface are encouraged to handle exceptions locally where + *

+ * Implementations of this interface are encouraged to handle exceptions locally where * it makes sense or alternatively let the exception bubble up in which case by default * the exception is logged and the session closed with * {@link CloseStatus#SERVER_ERROR SERVER_ERROR(1011)}. The exception handling @@ -68,7 +68,13 @@ public interface WebSocketHandler { void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception; /** - * Whether the WebSocketHandler handles messages in parts. + * Whether the WebSocketHandler handles partial messages. If this flag is set to + * {@code true} and the underlying WebSocket server supports partial messages, + * then a large WebSocket message, or one of an unknown size may be split and + * maybe received over multiple calls to + * {@link #handleMessage(WebSocketSession, WebSocketMessage)}. The flag + * {@link org.springframework.web.socket.WebSocketMessage#isLast()} indicates if + * the message is partial and whether it is the last part. */ boolean supportsPartialMessages(); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java index c33697f4ae..f5f9433d58 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java @@ -25,72 +25,20 @@ import org.springframework.util.ObjectUtils; * @author Rossen Stoyanchev * @since 4.0 */ -public abstract class WebSocketMessage { - - private final T payload; - - private final boolean last; - - - /** - * Create a new {@link WebSocketMessage} instance with the given payload. - */ - WebSocketMessage(T payload) { - this(payload, true); - } - - /** - * Create a new {@link WebSocketMessage} instance with the given payload. - * @param payload a non-null payload - */ - WebSocketMessage(T payload, boolean isLast) { - Assert.notNull(payload, "payload is required"); - this.payload = payload; - this.last = isLast; - } - +public interface WebSocketMessage { /** * Returns the message payload. This will never be {@code null}. */ - public T getPayload() { - return this.payload; - } + T getPayload(); /** - * Whether this is the last part of a message, when partial message support on a - * {@link WebSocketHandler} is enabled. If partial message support is not enabled the - * returned value is always {@code true}. + * When partial message support is available and requested via + * {@link org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()}, + * this method returns {@literal true} if the current message is the last part of + * the complete WebSocket message sent by the client. Otherwise {@literal false} + * is returned if partial message support is either not available or not enabled. */ - public boolean isLast() { - return this.last; - } - - @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); - } - - @Override - public String toString() { - return getClass().getSimpleName() + " payload= " + toStringPayload() - + ", length=" + getPayloadSize() + ", last=" + isLast() + "]"; - } - - protected abstract String toStringPayload(); - - protected abstract int getPayloadSize(); + boolean isLast(); } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java b/spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java index 8e01c903bd..eb0dfc4c56 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java @@ -32,8 +32,6 @@ import org.springframework.web.socket.WebSocketSession; /** * An abstract base class for implementations of {@link WebSocketSession}. * - * @param T the type of the native (or delegate) WebSocket session - * * @author Rossen Stoyanchev * @since 4.0 */ diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java b/spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java index a703514fbc..2972c7b3bb 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java @@ -19,22 +19,32 @@ package org.springframework.web.socket.adapter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketListener; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.common.OpCode; import org.springframework.util.Assert; import org.springframework.web.socket.BinaryMessage; import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.PongMessage; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator; +import java.nio.ByteBuffer; + /** * Adapts {@link WebSocketHandler} to the Jetty 9 WebSocket API. * - * @author Phillip Webb * @author Rossen Stoyanchev * @since 4.0 */ -public class JettyWebSocketHandlerAdapter implements WebSocketListener { +@WebSocket +public class JettyWebSocketHandlerAdapter { private static final Log logger = LogFactory.getLog(JettyWebSocketHandlerAdapter.class); @@ -44,14 +54,16 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener { public JettyWebSocketHandlerAdapter(WebSocketHandler webSocketHandler, JettyWebSocketSession wsSession) { + Assert.notNull(webSocketHandler, "webSocketHandler must not be null"); Assert.notNull(wsSession, "wsSession must not be null"); + this.webSocketHandler = webSocketHandler; this.wsSession = wsSession; } - @Override + @OnWebSocketConnect public void onWebSocketConnect(Session session) { try { this.wsSession.initializeNativeSession(session); @@ -62,7 +74,7 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener { } } - @Override + @OnWebSocketMessage public void onWebSocketText(String payload) { TextMessage message = new TextMessage(payload); try { @@ -73,9 +85,9 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener { } } - @Override - public void onWebSocketBinary(byte[] payload, int offset, int len) { - BinaryMessage message = new BinaryMessage(payload, offset, len, true); + @OnWebSocketMessage + public void onWebSocketBinary(byte[] payload, int offset, int length) { + BinaryMessage message = new BinaryMessage(payload, offset, length, true); try { this.webSocketHandler.handleMessage(this.wsSession, message); } @@ -84,7 +96,20 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener { } } - @Override + @OnWebSocketFrame + public void onWebSocketFrame(Frame frame) { + if (OpCode.PONG == frame.getOpCode()) { + PongMessage message = new PongMessage(frame.getPayload()); + try { + this.webSocketHandler.handleMessage(this.wsSession, message); + } + catch (Throwable t) { + ExceptionWebSocketHandlerDecorator.tryCloseWithError(this.wsSession, t, logger); + } + } + } + + @OnWebSocketClose public void onWebSocketClose(int statusCode, String reason) { CloseStatus closeStatus = new CloseStatus(statusCode, reason); try { @@ -95,7 +120,7 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener { } } - @Override + @OnWebSocketError public void onWebSocketError(Throwable cause) { try { this.webSocketHandler.handleTransportError(this.wsSession, cause); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java b/spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java index 993afda11f..ff7bbba910 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java @@ -35,6 +35,8 @@ import org.springframework.util.CollectionUtils; */ public class WebSocketHttpHeaders extends HttpHeaders { + private static final long serialVersionUID = -6644521016187828916L; + public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept"; public static final String SEC_WEBSOCKET_EXTENSIONS = "Sec-WebSocket-Extensions"; diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java index e769d5b652..b9e50bb0c5 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java @@ -69,7 +69,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes new WebSocketHandlerAdapter(), getWsBaseUrl() + "/ws").get(); TestWebSocketHandler serverHandler = this.wac.getBean(TestWebSocketHandler.class); - assertTrue(serverHandler.latch.await(2, TimeUnit.SECONDS)); + assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS)); session.close(); } @@ -81,7 +81,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes new WebSocketHandlerAdapter(), getWsBaseUrl() + "/sockjs/websocket").get(); TestWebSocketHandler serverHandler = this.wac.getBean(TestWebSocketHandler.class); - assertTrue(serverHandler.latch.await(2, TimeUnit.SECONDS)); + assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS)); session.close(); } @@ -113,11 +113,11 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes private static class TestWebSocketHandler extends WebSocketHandlerAdapter { - private CountDownLatch latch = new CountDownLatch(1); + private CountDownLatch connectLatch = new CountDownLatch(1); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { - this.latch.countDown(); + this.connectLatch.countDown(); } }