Skip to content

Commit 164a9f9

Browse files
committed
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
1 parent 7d5b34a commit 164a9f9

File tree

14 files changed

+238
-186
lines changed

14 files changed

+238
-186
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
*/
2929
public class MessageHandlingException extends MessagingException {
3030

31+
private static final long serialVersionUID = 690969923668400297L;
32+
3133

3234
public MessageHandlingException(Message<?> message, String description, Throwable cause) {
3335
super(message, description, cause);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
*/
2727
public class BrokerAvailabilityEvent extends ApplicationEvent {
2828

29+
private static final long serialVersionUID = -8156742505179181002L;
30+
2931
private final boolean brokerAvailable;
3032

33+
3134
/**
3235
* Creates a new {@code BrokerAvailabilityEvent}.
3336
*
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.web.socket;
18+
19+
import org.springframework.util.Assert;
20+
import org.springframework.util.ObjectUtils;
21+
22+
/**
23+
* A message that can be handled or sent on a WebSocket connection.
24+
*
25+
* @author Rossen Stoyanchev
26+
* @since 4.0
27+
*/
28+
public abstract class AbstractWebSocketMessage<T> implements WebSocketMessage<T> {
29+
30+
private final T payload;
31+
32+
private final boolean last;
33+
34+
35+
/**
36+
* Create a new WebSocket message with the given payload.
37+
*
38+
* @param payload the non-null payload
39+
*/
40+
AbstractWebSocketMessage(T payload) {
41+
this(payload, true);
42+
}
43+
44+
/**
45+
* Create a new WebSocket message given payload representing the full or partial
46+
* message content. When the {@code isLast} boolean flag is set to {@code false}
47+
* the message is sent as partial content and more partial messages will be
48+
* expected until the boolean flag is set to {@code true}.
49+
*
50+
* @param payload the non-null payload
51+
* @param isLast if the message is the last of a series of partial messages
52+
*/
53+
AbstractWebSocketMessage(T payload, boolean isLast) {
54+
Assert.notNull(payload, "payload is required");
55+
this.payload = payload;
56+
this.last = isLast;
57+
}
58+
59+
60+
/**
61+
* Return the message payload, never be {@code null}.
62+
*/
63+
public T getPayload() {
64+
return this.payload;
65+
}
66+
67+
/**
68+
* Whether this is the last part of a message sent as a series of partial messages.
69+
*/
70+
public boolean isLast() {
71+
return this.last;
72+
}
73+
74+
@Override
75+
public int hashCode() {
76+
return AbstractWebSocketMessage.class.hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.payload);
77+
}
78+
79+
@Override
80+
public boolean equals(Object other) {
81+
if (this == other) {
82+
return true;
83+
}
84+
if (!(other instanceof AbstractWebSocketMessage)) {
85+
return false;
86+
}
87+
AbstractWebSocketMessage otherMessage = (AbstractWebSocketMessage) other;
88+
return ObjectUtils.nullSafeEquals(this.payload, otherMessage.payload);
89+
}
90+
91+
@Override
92+
public String toString() {
93+
return getClass().getSimpleName() + " payload= " + toStringPayload()
94+
+ ", length=" + getPayloadSize() + ", last=" + isLast() + "]";
95+
}
96+
97+
protected abstract String toStringPayload();
98+
99+
protected abstract int getPayloadSize();
100+
101+
}

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

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,92 +19,82 @@
1919
import java.nio.ByteBuffer;
2020

2121
/**
22-
* A {@link WebSocketMessage} that contains a binary {@link ByteBuffer} payload.
22+
* A binary WebSocket message.
2323
*
2424
* @author Rossen Stoyanchev
2525
* @since 4.0
2626
*/
27-
public final class BinaryMessage extends WebSocketMessage<ByteBuffer> {
28-
29-
private byte[] bytes;
27+
public final class BinaryMessage extends AbstractWebSocketMessage<ByteBuffer> {
3028

3129

3230
/**
33-
* Create a new {@link BinaryMessage} instance.
31+
* Create a new binary WebSocket message with the given ByteBuffer payload.
32+
*
3433
* @param payload the non-null payload
3534
*/
3635
public BinaryMessage(ByteBuffer payload) {
37-
this(payload, true);
36+
super(payload, true);
3837
}
3938

4039
/**
41-
* Create a new {@link BinaryMessage} instance.
40+
* Create a new binary WebSocket message with the given payload representing the
41+
* full or partial message content. When the {@code isLast} boolean flag is set
42+
* to {@code false} the message is sent as partial content and more partial
43+
* messages will be expected until the boolean flag is set to {@code true}.
44+
*
4245
* @param payload the non-null payload
4346
* @param isLast if the message is the last of a series of partial messages
4447
*/
4548
public BinaryMessage(ByteBuffer payload, boolean isLast) {
4649
super(payload, isLast);
47-
this.bytes = null;
4850
}
4951

5052
/**
51-
* Create a new {@link BinaryMessage} instance.
52-
* @param payload the non-null payload
53+
* Create a new binary WebSocket message with the given byte[] payload.
54+
*
55+
* @param payload a non-null payload; note that this value is not copied so care
56+
* must be taken not to modify the array.
5357
*/
5458
public BinaryMessage(byte[] payload) {
55-
this(payload, 0, (payload == null ? 0 : payload.length), true);
59+
this(payload, true);
5660
}
5761

5862
/**
59-
* Create a new {@link BinaryMessage} instance.
60-
* @param payload the non-null payload
63+
* Create a new binary WebSocket message with the given byte[] payload representing
64+
* the full or partial message content. When the {@code isLast} boolean flag is set
65+
* to {@code false} the message is sent as partial content and more partial
66+
* messages will be expected until the boolean flag is set to {@code true}.
67+
*
68+
* @param payload a non-null payload; note that this value is not copied so care
69+
* must be taken not to modify the array.
6170
* @param isLast if the message is the last of a series of partial messages
6271
*/
6372
public BinaryMessage(byte[] payload, boolean isLast) {
64-
this(payload, 0, (payload == null ? 0 : payload.length), isLast);
73+
this(payload, 0, ((payload == null) ? 0 : payload.length), isLast);
6574
}
6675

6776
/**
68-
* Create a new {@link BinaryMessage} instance by wrapping an existing byte array.
69-
* @param payload a non-null payload, NOTE: this value is not copied so care must be
70-
* taken not to modify the array.
71-
* @param offset the offet into the array where the payload starts
72-
* @param len the length of the array considered for the payload
77+
* Create a new binary WebSocket message by wrapping an existing byte array.
78+
*
79+
* @param payload a non-null payload; note that this value is not copied so care
80+
* must be taken not to modify the array.
81+
* @param offset the offset into the array where the payload starts
82+
* @param length the length of the array considered for the payload
7383
* @param isLast if the message is the last of a series of partial messages
7484
*/
75-
public BinaryMessage(byte[] payload, int offset, int len, boolean isLast) {
76-
super(payload != null ? ByteBuffer.wrap(payload, offset, len) : null, isLast);
77-
if(offset == 0 && len == payload.length) {
78-
this.bytes = payload;
79-
}
85+
public BinaryMessage(byte[] payload, int offset, int length, boolean isLast) {
86+
super((payload != null) ? ByteBuffer.wrap(payload, offset, length) : null, isLast);
8087
}
8188

8289

83-
/**
84-
* Returns access to the message payload as a byte array. NOTE: the returned array
85-
* should be considered read-only and should not be modified.
86-
*/
87-
public byte[] getByteArray() {
88-
if(this.bytes == null && getPayload() != null) {
89-
this.bytes = getRemainingBytes(getPayload());
90-
}
91-
return this.bytes;
92-
}
93-
94-
private byte[] getRemainingBytes(ByteBuffer payload) {
95-
byte[] result = new byte[getPayload().remaining()];
96-
getPayload().get(result);
97-
return result;
98-
}
99-
10090
@Override
10191
protected int getPayloadSize() {
102-
return (getPayload() != null) ? getPayload().remaining() : 0;
92+
return getPayload().remaining();
10393
}
10494

10595
@Override
10696
protected String toStringPayload() {
107-
return (getPayload() != null) ? getPayload().toString() : null;
97+
return getPayload().toString();
10898
}
10999

110100
}

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,34 @@
2424
* @author Rossen Stoyanchev
2525
* @since 4.0
2626
*/
27-
public final class PingMessage extends WebSocketMessage<ByteBuffer> {
27+
public final class PingMessage extends AbstractWebSocketMessage<ByteBuffer> {
2828

2929

30+
/**
31+
* Create a new ping message with an empty payload.
32+
*/
33+
public PingMessage() {
34+
super(ByteBuffer.allocate(0));
35+
}
36+
37+
/**
38+
* Create a new ping message with the given ByteBuffer payload.
39+
*
40+
* @param payload the non-null payload
41+
*/
3042
public PingMessage(ByteBuffer payload) {
3143
super(payload);
3244
}
3345

46+
3447
@Override
3548
protected int getPayloadSize() {
36-
return (getPayload() != null) ? getPayload().remaining() : 0;
49+
return getPayload().remaining();
3750
}
3851

3952
@Override
4053
protected String toStringPayload() {
41-
return (getPayload() != null) ? getPayload().toString() : null;
54+
return getPayload().toString();
4255
}
4356

4457
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,26 @@
2424
* @author Rossen Stoyanchev
2525
* @since 4.0
2626
*/
27-
public final class PongMessage extends WebSocketMessage<ByteBuffer> {
27+
public final class PongMessage extends AbstractWebSocketMessage<ByteBuffer> {
2828

2929

30+
/**
31+
* Create a new pong message with an empty payload.
32+
*/
33+
public PongMessage() {
34+
super(ByteBuffer.allocate(0));
35+
}
36+
37+
/**
38+
* Create a new pong message with the given ByteBuffer payload.
39+
*
40+
* @param payload the non-null payload
41+
*/
3042
public PongMessage(ByteBuffer payload) {
3143
super(payload);
3244
}
3345

46+
3447
@Override
3548
protected int getPayloadSize() {
3649
return (getPayload() != null) ? getPayload().remaining() : 0;

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

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)