Introduce CONNECT_ACK message type

Previously, handling of a STOMP CONNECT message and sending of a
CONNECTED response was performed by StompProtocolHandler if it was
backed by SimpleBrokerMessageHandler, or left up to the real message
broker if it was backed by StompBrokerRelayMessageHandler. This
wasn't ideal as it should be StompProtocolHandler's job to simply map
messages to and from the STOMP protocol, not to do part of the
broker's job and respond directly to CONNECT.

This commit introduces a new message type, CONNECT_ACK. When it
receives a CONNECT message, SimpleBrokerMessageHandler will now
respond with a CONNECT_ACK message that StompProtocolHandler can map
into a STOMP CONNECTED message. The CONNECT_ACK message contains the
CONNECT message as a header so that StompProtocolHandler has access to
its accept-version header.

StompProtocolHandler has been simplified so that a CONNECT message
is always passed to the output channel, irrespective of whether it's
backed by a simple broker or a real broker. The handleConnect flag,
and the code that would set it correctly depending on the app's
configuration, has been removed.
This commit is contained in:
Andy Wilkinson
2013-09-27 15:41:46 +01:00
committed by Rossen Stoyanchev
parent b2f31a3c74
commit 5025c304b8
9 changed files with 90 additions and 82 deletions

View File

@@ -53,7 +53,7 @@ public class ServletStompEndpointRegistryTests {
this.webSocketHandler = new SubProtocolWebSocketHandler(channel);
this.queueSuffixResolver = new SimpleUserQueueSuffixResolver();
TaskScheduler taskScheduler = Mockito.mock(TaskScheduler.class);
this.registry = new ServletStompEndpointRegistry(webSocketHandler, queueSuffixResolver, taskScheduler, false);
this.registry = new ServletStompEndpointRegistry(webSocketHandler, queueSuffixResolver, taskScheduler);
}

View File

@@ -30,6 +30,8 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.support.MessageBuilder;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -111,6 +113,24 @@ public class SimpleBrokerMessageHandlerTests {
assertCapturedMessage(sess2, "sub3", "/bar");
}
@Test
public void connect() {
String sess1 = "sess1";
this.messageHandler.start();
Message<String> connectMessage = createConnectMessage(sess1);
this.messageHandler.handleMessage(connectMessage);
verify(this.clientChannel, times(1)).send(this.messageCaptor.capture());
Message<?> connectAckMessage = this.messageCaptor.getValue();
SimpMessageHeaderAccessor connectAckHeaders = SimpMessageHeaderAccessor.wrap(connectAckMessage);
assertEquals(connectMessage, connectAckHeaders.getHeader(SimpMessageHeaderAccessor.CONNECT_MESSAGE_HEADER));
assertEquals(sess1, connectAckHeaders.getSessionId());
}
protected Message<String> createSubscriptionMessage(String sessionId, String subcriptionId, String destination) {
@@ -122,6 +142,13 @@ public class SimpleBrokerMessageHandlerTests {
return MessageBuilder.withPayload("").copyHeaders(headers.toMap()).build();
}
protected Message<String> createConnectMessage(String sessionId) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
headers.setSessionId(sessionId);
return MessageBuilder.withPayloadAndHeaders("", headers).build();
}
protected Message<String> createMessage(String destination, String payload) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);

View File

@@ -26,6 +26,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.support.TestPrincipal;
import org.springframework.web.socket.support.TestWebSocketSession;
@@ -61,20 +64,25 @@ public class StompProtocolHandlerTests {
}
@Test
public void connectedResponseIsSentWhenHandlingConnect() {
this.stompHandler.setHandleConnect(true);
public void connectedResponseIsSentWhenConnectAckIsToBeSentToClient() {
StompHeaderAccessor connectHeaders = StompHeaderAccessor.create(StompCommand.CONNECT);
connectHeaders.setHeartbeat(10000, 10000);
connectHeaders.setNativeHeader(StompHeaderAccessor.STOMP_ACCEPT_VERSION_HEADER, "1.0,1.1");
TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT).headers(
"login:guest", "passcode:guest", "accept-version:1.1,1.0", "heart-beat:10000,10000").build();
Message<?> connectMessage = MessageBuilder.withPayloadAndHeaders(new byte[0], connectHeaders).build();
this.stompHandler.handleMessageFromClient(this.session, textMessage, this.channel);
SimpMessageHeaderAccessor connectAckHeaders = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT_ACK);
connectAckHeaders.setHeader(SimpMessageHeaderAccessor.CONNECT_MESSAGE_HEADER, connectMessage);
Message<byte[]> connectAck = MessageBuilder.withPayloadAndHeaders(new byte[0], connectAckHeaders).build();
this.stompHandler.handleMessageToClient(this.session, connectAck);
verifyNoMoreInteractions(this.channel);
// Check CONNECTED reply
assertEquals(1, this.session.getSentMessages().size());
textMessage = (TextMessage) this.session.getSentMessages().get(0);
TextMessage textMessage = (TextMessage) this.session.getSentMessages().get(0);
Message<?> message = new StompDecoder().decode(ByteBuffer.wrap(textMessage.getPayload().getBytes()));
StompHeaderAccessor replyHeaders = StompHeaderAccessor.wrap(message);
@@ -86,8 +94,7 @@ public class StompProtocolHandlerTests {
}
@Test
public void connectIsForwardedWhenNotHandlingConnect() {
this.stompHandler.setHandleConnect(false);
public void messagesAreAugmentedAndForwarded() {
TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT).headers(
"login:guest", "passcode:guest", "accept-version:1.1,1.0", "heart-beat:10000,10000").build();