Browse Source

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
pull/398/head
Rossen Stoyanchev 11 years ago
parent
commit
164a9f938c
  1. 2
      spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java
  2. 3
      spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java
  3. 101
      spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java
  4. 76
      spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java
  5. 19
      spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java
  6. 15
      spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java
  7. 55
      spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java
  8. 16
      spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java
  9. 12
      spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java
  10. 68
      spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java
  11. 2
      spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java
  12. 45
      spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java
  13. 2
      spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java
  14. 8
      spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java

2
spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageHandlingException.java

@ -28,6 +28,8 @@ import org.springframework.messaging.MessagingException; @@ -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);

3
spring-messaging/src/main/java/org/springframework/messaging/simp/BrokerAvailabilityEvent.java

@ -26,8 +26,11 @@ import org.springframework.context.ApplicationEvent; @@ -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}.
*

101
spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java

@ -0,0 +1,101 @@ @@ -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();
}

76
spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java

@ -19,92 +19,82 @@ package org.springframework.web.socket; @@ -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();
}
}

19
spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java

@ -24,21 +24,34 @@ import java.nio.ByteBuffer; @@ -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();
}
}

15
spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java

@ -24,13 +24,26 @@ import java.nio.ByteBuffer; @@ -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;

55
spring-websocket/src/main/java/org/springframework/web/socket/ReaderTextMessage.java

@ -1,55 +0,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();
}
}

16
spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java

@ -17,15 +17,17 @@ @@ -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> { @@ -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);

12
spring-websocket/src/main/java/org/springframework/web/socket/WebSocketHandler.java

@ -18,8 +18,8 @@ package org.springframework.web.socket; @@ -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 { @@ -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();

68
spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java

@ -25,72 +25,20 @@ import org.springframework.util.ObjectUtils; @@ -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();
}

2
spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSesssion.java

@ -32,8 +32,6 @@ import org.springframework.web.socket.WebSocketSession; @@ -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
*/

45
spring-websocket/src/main/java/org/springframework/web/socket/adapter/JettyWebSocketHandlerAdapter.java

@ -19,22 +19,32 @@ package org.springframework.web.socket.adapter; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -95,7 +120,7 @@ public class JettyWebSocketHandlerAdapter implements WebSocketListener {
}
}
@Override
@OnWebSocketError
public void onWebSocketError(Throwable cause) {
try {
this.webSocketHandler.handleTransportError(this.wsSession, cause);

2
spring-websocket/src/main/java/org/springframework/web/socket/support/WebSocketHttpHeaders.java

@ -35,6 +35,8 @@ import org.springframework.util.CollectionUtils; @@ -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";

8
spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java

@ -69,7 +69,7 @@ public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTes @@ -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 @@ -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 @@ -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();
}
}

Loading…
Cancel
Save