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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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}.
|
||||
*
|
||||
|
||||
@@ -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<T> implements WebSocketMessage<T> {
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -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<ByteBuffer> {
|
||||
|
||||
private byte[] bytes;
|
||||
public final class BinaryMessage extends AbstractWebSocketMessage<ByteBuffer> {
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,21 +24,34 @@ import java.nio.ByteBuffer;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class PingMessage extends WebSocketMessage<ByteBuffer> {
|
||||
public final class PingMessage extends AbstractWebSocketMessage<ByteBuffer> {
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,13 +24,26 @@ import java.nio.ByteBuffer;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class PongMessage extends WebSocketMessage<ByteBuffer> {
|
||||
public final class PongMessage extends AbstractWebSocketMessage<ByteBuffer> {
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -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<String> {
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<String> {
|
||||
public final class TextMessage extends AbstractWebSocketMessage<String> {
|
||||
|
||||
|
||||
/**
|
||||
* 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<String> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.web.socket;
|
||||
|
||||
/**
|
||||
* A handler for WebSocket messages and lifecycle events.
|
||||
*
|
||||
* <p>Implementations of this interface are encouraged to handle exceptions locally where
|
||||
* <p>
|
||||
* 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();
|
||||
|
||||
|
||||
@@ -25,72 +25,20 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class WebSocketMessage<T> {
|
||||
|
||||
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<T> {
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user