Search in sources :

Example 21 with StompHeaderAccessor

use of org.springframework.messaging.simp.stomp.StompHeaderAccessor in project spring-framework by spring-projects.

the class StompSubProtocolHandler method convertConnectAcktoStompConnected.

/**
	 * The simple broker produces {@code SimpMessageType.CONNECT_ACK} that's not STOMP
	 * specific and needs to be turned into a STOMP CONNECTED frame.
	 */
private StompHeaderAccessor convertConnectAcktoStompConnected(StompHeaderAccessor connectAckHeaders) {
    String name = StompHeaderAccessor.CONNECT_MESSAGE_HEADER;
    Message<?> message = (Message<?>) connectAckHeaders.getHeader(name);
    if (message == null) {
        throw new IllegalStateException("Original STOMP CONNECT not found in " + connectAckHeaders);
    }
    StompHeaderAccessor connectHeaders = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
    StompHeaderAccessor connectedHeaders = StompHeaderAccessor.create(StompCommand.CONNECTED);
    Set<String> acceptVersions = connectHeaders.getAcceptVersion();
    if (acceptVersions.contains("1.2")) {
        connectedHeaders.setVersion("1.2");
    } else if (acceptVersions.contains("1.1")) {
        connectedHeaders.setVersion("1.1");
    } else if (!acceptVersions.isEmpty()) {
        throw new IllegalArgumentException("Unsupported STOMP version '" + acceptVersions + "'");
    }
    long[] heartbeat = (long[]) connectAckHeaders.getHeader(SimpMessageHeaderAccessor.HEART_BEAT_HEADER);
    if (heartbeat != null) {
        connectedHeaders.setHeartbeat(heartbeat[0], heartbeat[1]);
    } else {
        connectedHeaders.setHeartbeat(0, 0);
    }
    return connectedHeaders;
}
Also used : TextMessage(org.springframework.web.socket.TextMessage) Message(org.springframework.messaging.Message) WebSocketMessage(org.springframework.web.socket.WebSocketMessage) BinaryMessage(org.springframework.web.socket.BinaryMessage) StompHeaderAccessor(org.springframework.messaging.simp.stomp.StompHeaderAccessor)

Example 22 with StompHeaderAccessor

use of org.springframework.messaging.simp.stomp.StompHeaderAccessor in project spring-framework by spring-projects.

the class StompSubProtocolHandler method sendErrorMessage.

/**
	 * Invoked when no
	 * {@link #setErrorHandler(StompSubProtocolErrorHandler) errorHandler}
	 * is configured to send an ERROR frame to the client.
	 */
private void sendErrorMessage(WebSocketSession session, Throwable error) {
    StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.ERROR);
    headerAccessor.setMessage(error.getMessage());
    byte[] bytes = this.stompEncoder.encode(headerAccessor.getMessageHeaders(), EMPTY_PAYLOAD);
    try {
        session.sendMessage(new TextMessage(bytes));
    } catch (Throwable ex) {
        // Could be part of normal workflow (e.g. browser tab closed)
        logger.debug("Failed to send STOMP ERROR to client", ex);
    }
}
Also used : StompHeaderAccessor(org.springframework.messaging.simp.stomp.StompHeaderAccessor) TextMessage(org.springframework.web.socket.TextMessage)

Example 23 with StompHeaderAccessor

use of org.springframework.messaging.simp.stomp.StompHeaderAccessor in project spring-framework by spring-projects.

the class StompSubProtocolHandler method handleMessageToClient.

/**
	 * Handle STOMP messages going back out to WebSocket clients.
	 */
@Override
@SuppressWarnings("unchecked")
public void handleMessageToClient(WebSocketSession session, Message<?> message) {
    if (!(message.getPayload() instanceof byte[])) {
        if (logger.isErrorEnabled()) {
            logger.error("Expected byte[] payload. Ignoring " + message + ".");
        }
        return;
    }
    StompHeaderAccessor accessor = getStompHeaderAccessor(message);
    StompCommand command = accessor.getCommand();
    if (StompCommand.MESSAGE.equals(command)) {
        if (accessor.getSubscriptionId() == null && logger.isWarnEnabled()) {
            logger.warn("No STOMP \"subscription\" header in " + message);
        }
        String origDestination = accessor.getFirstNativeHeader(SimpMessageHeaderAccessor.ORIGINAL_DESTINATION);
        if (origDestination != null) {
            accessor = toMutableAccessor(accessor, message);
            accessor.removeNativeHeader(SimpMessageHeaderAccessor.ORIGINAL_DESTINATION);
            accessor.setDestination(origDestination);
        }
    } else if (StompCommand.CONNECTED.equals(command)) {
        this.stats.incrementConnectedCount();
        accessor = afterStompSessionConnected(message, accessor, session);
        if (this.eventPublisher != null && StompCommand.CONNECTED.equals(command)) {
            try {
                SimpAttributes simpAttributes = new SimpAttributes(session.getId(), session.getAttributes());
                SimpAttributesContextHolder.setAttributes(simpAttributes);
                Principal user = getUser(session);
                publishEvent(new SessionConnectedEvent(this, (Message<byte[]>) message, user));
            } finally {
                SimpAttributesContextHolder.resetAttributes();
            }
        }
    }
    byte[] payload = (byte[]) message.getPayload();
    if (StompCommand.ERROR.equals(command) && getErrorHandler() != null) {
        Message<byte[]> errorMessage = getErrorHandler().handleErrorMessageToClient((Message<byte[]>) message);
        accessor = MessageHeaderAccessor.getAccessor(errorMessage, StompHeaderAccessor.class);
        Assert.state(accessor != null, "Expected STOMP headers");
        payload = errorMessage.getPayload();
    }
    sendToClient(session, accessor, payload);
}
Also used : SimpAttributes(org.springframework.messaging.simp.SimpAttributes) StompHeaderAccessor(org.springframework.messaging.simp.stomp.StompHeaderAccessor) StompCommand(org.springframework.messaging.simp.stomp.StompCommand) Principal(java.security.Principal)

Example 24 with StompHeaderAccessor

use of org.springframework.messaging.simp.stomp.StompHeaderAccessor in project spring-framework by spring-projects.

the class RestTemplateXhrTransportTests method connectReceiveAndCloseWithStompFrame.

@Test
public void connectReceiveAndCloseWithStompFrame() throws Exception {
    StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.SEND);
    accessor.setDestination("/destination");
    MessageHeaders headers = accessor.getMessageHeaders();
    Message<byte[]> message = MessageBuilder.createMessage("body".getBytes(StandardCharsets.UTF_8), headers);
    byte[] bytes = new StompEncoder().encode(message);
    TextMessage textMessage = new TextMessage(bytes);
    SockJsFrame frame = SockJsFrame.messageFrame(new Jackson2SockJsMessageCodec(), textMessage.getPayload());
    String body = "o\n" + frame.getContent() + "\n" + "c[3000,\"Go away!\"]";
    ClientHttpResponse response = response(HttpStatus.OK, body);
    connect(response);
    verify(this.webSocketHandler).afterConnectionEstablished(any());
    verify(this.webSocketHandler).handleMessage(any(), eq(textMessage));
    verify(this.webSocketHandler).afterConnectionClosed(any(), eq(new CloseStatus(3000, "Go away!")));
    verifyNoMoreInteractions(this.webSocketHandler);
}
Also used : Jackson2SockJsMessageCodec(org.springframework.web.socket.sockjs.frame.Jackson2SockJsMessageCodec) StompEncoder(org.springframework.messaging.simp.stomp.StompEncoder) StompHeaderAccessor(org.springframework.messaging.simp.stomp.StompHeaderAccessor) MessageHeaders(org.springframework.messaging.MessageHeaders) CloseStatus(org.springframework.web.socket.CloseStatus) SockJsFrame(org.springframework.web.socket.sockjs.frame.SockJsFrame) ClientHttpResponse(org.springframework.http.client.ClientHttpResponse) TextMessage(org.springframework.web.socket.TextMessage) Test(org.junit.Test)

Example 25 with StompHeaderAccessor

use of org.springframework.messaging.simp.stomp.StompHeaderAccessor in project spring-framework by spring-projects.

the class StompSubProtocolHandlerTests method handleMessageFromClient.

@Test
public void handleMessageFromClient() {
    TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT).headers("login:guest", "passcode:guest", "accept-version:1.1,1.0", "heart-beat:10000,10000").build();
    this.protocolHandler.afterSessionStarted(this.session, this.channel);
    this.protocolHandler.handleMessageFromClient(this.session, textMessage, this.channel);
    verify(this.channel).send(this.messageCaptor.capture());
    Message<?> actual = this.messageCaptor.getValue();
    assertNotNull(actual);
    assertEquals("s1", SimpMessageHeaderAccessor.getSessionId(actual.getHeaders()));
    assertNotNull(SimpMessageHeaderAccessor.getSessionAttributes(actual.getHeaders()));
    assertNotNull(SimpMessageHeaderAccessor.getUser(actual.getHeaders()));
    assertEquals("joe", SimpMessageHeaderAccessor.getUser(actual.getHeaders()).getName());
    assertNotNull(SimpMessageHeaderAccessor.getHeartbeat(actual.getHeaders()));
    assertArrayEquals(new long[] { 10000, 10000 }, SimpMessageHeaderAccessor.getHeartbeat(actual.getHeaders()));
    StompHeaderAccessor stompAccessor = StompHeaderAccessor.wrap(actual);
    assertEquals(StompCommand.CONNECT, stompAccessor.getCommand());
    assertEquals("guest", stompAccessor.getLogin());
    assertEquals("guest", stompAccessor.getPasscode());
    assertArrayEquals(new long[] { 10000, 10000 }, stompAccessor.getHeartbeat());
    assertEquals(new HashSet<>(Arrays.asList("1.1", "1.0")), stompAccessor.getAcceptVersion());
    assertEquals(0, this.session.getSentMessages().size());
}
Also used : StompHeaderAccessor(org.springframework.messaging.simp.stomp.StompHeaderAccessor) TextMessage(org.springframework.web.socket.TextMessage) Test(org.junit.Test)

Aggregations

StompHeaderAccessor (org.springframework.messaging.simp.stomp.StompHeaderAccessor)38 Test (org.junit.Test)28 TextMessage (org.springframework.web.socket.TextMessage)19 Message (org.springframework.messaging.Message)10 BinaryMessage (org.springframework.web.socket.BinaryMessage)9 SimpMessageHeaderAccessor (org.springframework.messaging.simp.SimpMessageHeaderAccessor)6 WebSocketMessage (org.springframework.web.socket.WebSocketMessage)5 StompEncoder (org.springframework.messaging.simp.stomp.StompEncoder)4 StompHeaders (org.springframework.messaging.simp.stomp.StompHeaders)3 PongMessage (org.springframework.web.socket.PongMessage)3 Principal (java.security.Principal)2 MessageHeaders (org.springframework.messaging.MessageHeaders)2 SimpAttributes (org.springframework.messaging.simp.SimpAttributes)2 SimpAnnotationMethodMessageHandler (org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler)2 MessageHeaderAccessor (org.springframework.messaging.support.MessageHeaderAccessor)2 ByteBuffer (java.nio.ByteBuffer)1 ApplicationContext (org.springframework.context.ApplicationContext)1 ApplicationEventPublisher (org.springframework.context.ApplicationEventPublisher)1 AnnotationConfigApplicationContext (org.springframework.context.annotation.AnnotationConfigApplicationContext)1 ClientHttpResponse (org.springframework.http.client.ClientHttpResponse)1