/** * After a DISCONNECT there should be no more client frames so we can * close the connection pro-actively. However, if the DISCONNECT has a * receipt header we leave the connection open and expect the server will * respond with a RECEIPT and then close the connection. * @see <a href="http://stomp.github.io/stomp-specification-1.2.html#DISCONNECT"> * STOMP Specification 1.2 DISCONNECT</a> */ private void afterDisconnectSent(StompHeaderAccessor accessor) { if (accessor.getReceipt() == null) { try { clearConnection(); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failure while clearing TCP connection state in session " + this.sessionId, ex); } } } }
@Nullable private String getDisconnectReceipt(SimpMessageHeaderAccessor simpHeaders) { String name = StompHeaderAccessor.DISCONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) simpHeaders.getHeader(name); if (message != null) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (accessor != null) { return accessor.getReceipt(); } } return null; }
@Override @Nullable public Message<byte[]> handleClientMessageProcessingError(@Nullable Message<byte[]> clientMessage, Throwable ex) { StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.ERROR); accessor.setMessage(ex.getMessage()); accessor.setLeaveMutable(true); StompHeaderAccessor clientHeaderAccessor = null; if (clientMessage != null) { clientHeaderAccessor = MessageHeaderAccessor.getAccessor(clientMessage, StompHeaderAccessor.class); if (clientHeaderAccessor != null) { String receiptId = clientHeaderAccessor.getReceipt(); if (receiptId != null) { accessor.setReceiptId(receiptId); } } } return handleInternal(accessor, EMPTY_PAYLOAD, ex, clientHeaderAccessor); }
@Test public void sendWithReceipt() { this.session.afterConnected(this.connection); assertTrue(this.session.isConnected()); this.session.setTaskScheduler(mock(TaskScheduler.class)); this.session.setAutoReceipt(true); this.session.send("/topic/foo", "sample payload"); Message<byte[]> message = this.messageCaptor.getValue(); StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); assertNotNull(accessor.getReceipt()); StompHeaders stompHeaders = new StompHeaders(); stompHeaders.setDestination("/topic/foo"); stompHeaders.setReceipt("my-receipt"); this.session.send(stompHeaders, "sample payload"); message = this.messageCaptor.getValue(); accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); assertEquals("my-receipt", accessor.getReceipt()); }
@Override public String getShortLogMessage(Object payload) { StompCommand command = getCommand(); if (StompCommand.SUBSCRIBE.equals(command)) { return "SUBSCRIBE " + getDestination() + " id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.UNSUBSCRIBE.equals(command)) { return "UNSUBSCRIBE id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.SEND.equals(command)) { return "SEND " + getDestination() + appendSession() + appendPayload(payload); } else if (StompCommand.CONNECT.equals(command)) { Principal user = getUser(); return "CONNECT" + (user != null ? " user=" + user.getName() : "") + appendSession(); } else if (StompCommand.CONNECTED.equals(command)) { return "CONNECTED heart-beat=" + Arrays.toString(getHeartbeat()) + appendSession(); } else if (StompCommand.DISCONNECT.equals(command)) { String receipt = getReceipt(); return "DISCONNECT" + (receipt != null ? " receipt=" + receipt : "") + appendSession(); } else { return getDetailedLogMessage(payload); } }
/** * After a DISCONNECT there should be no more client frames so we can * close the connection pro-actively. However, if the DISCONNECT has a * receipt header we leave the connection open and expect the server will * respond with a RECEIPT and then close the connection. * @see <a href="http://stomp.github.io/stomp-specification-1.2.html#DISCONNECT"> * STOMP Specification 1.2 DISCONNECT</a> */ private void afterDisconnectSent(StompHeaderAccessor accessor) { if (accessor.getReceipt() == null) { try { clearConnection(); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failure while clearing TCP connection state in session " + this.sessionId, ex); } } } }
@Bean public ApplicationListener<SessionSubscribeEvent> webSocketEventListener( final AbstractSubscribableChannel clientOutboundChannel) { return event -> { Message<byte[]> message = event.getMessage(); StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message); if (stompHeaderAccessor.getReceipt() != null) { stompHeaderAccessor.setHeader("stompCommand", StompCommand.RECEIPT); stompHeaderAccessor.setReceiptId(stompHeaderAccessor.getReceipt()); clientOutboundChannel.send( MessageBuilder.createMessage(new byte[0], stompHeaderAccessor.getMessageHeaders())); } }; }
@Override public void onApplicationEvent(SessionSubscribeEvent event) { Message<byte[]> message = event.getMessage(); StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message); if (stompHeaderAccessor.getReceipt() != null) { stompHeaderAccessor.setHeader("stompCommand", StompCommand.RECEIPT); stompHeaderAccessor.setReceiptId(stompHeaderAccessor.getReceipt()); clientOutboundChannel.send( MessageBuilder.createMessage(new byte[0], stompHeaderAccessor.getMessageHeaders())); } }
@Override public String getShortLogMessage(Object payload) { StompCommand command = getCommand(); if (StompCommand.SUBSCRIBE.equals(command)) { return "SUBSCRIBE " + getDestination() + " id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.UNSUBSCRIBE.equals(command)) { return "UNSUBSCRIBE id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.SEND.equals(command)) { return "SEND " + getDestination() + appendSession() + appendPayload(payload); } else if (StompCommand.CONNECT.equals(command)) { Principal user = getUser(); return "CONNECT" + (user != null ? " user=" + user.getName() : "") + appendSession(); } else if (StompCommand.CONNECTED.equals(command)) { return "CONNECTED heart-beat=" + Arrays.toString(getHeartbeat()) + appendSession(); } else if (StompCommand.DISCONNECT.equals(command)) { String receipt = getReceipt(); return "DISCONNECT" + (receipt != null ? " receipt=" + receipt : "") + appendSession(); } else { return getDetailedLogMessage(payload); } }
/** * After a DISCONNECT there should be no more client frames so we can * close the connection pro-actively. However, if the DISCONNECT has a * receipt header we leave the connection open and expect the server will * respond with a RECEIPT and then close the connection. * @see <a href="http://stomp.github.io/stomp-specification-1.2.html#DISCONNECT"> * STOMP Specification 1.2 DISCONNECT</a> */ private void afterDisconnectSent(StompHeaderAccessor accessor) { if (accessor.getReceipt() == null) { try { clearConnection(); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failure while clearing TCP connection state in session " + this.sessionId, ex); } } } }
@Nullable private String getDisconnectReceipt(SimpMessageHeaderAccessor simpHeaders) { String name = StompHeaderAccessor.DISCONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) simpHeaders.getHeader(name); if (message != null) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (accessor != null) { return accessor.getReceipt(); } } return null; }
/** * After a DISCONNECT there should be no more client frames so we can * close the connection pro-actively. However, if the DISCONNECT has a * receipt header we leave the connection open and expect the server will * respond with a RECEIPT and then close the connection. * @see <a href="http://stomp.github.io/stomp-specification-1.2.html#DISCONNECT"> * STOMP Specification 1.2 DISCONNECT</a> */ private void afterDisconnectSent(StompHeaderAccessor accessor) { if (accessor.getReceipt() == null) { try { clearConnection(); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failure while clearing TCP connection state in session " + this.sessionId, ex); } } } }
@Nullable private String getDisconnectReceipt(SimpMessageHeaderAccessor simpHeaders) { String name = StompHeaderAccessor.DISCONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) simpHeaders.getHeader(name); if (message != null) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (accessor != null) { return accessor.getReceipt(); } } return null; }
@Override @Nullable public Message<byte[]> handleClientMessageProcessingError(@Nullable Message<byte[]> clientMessage, Throwable ex) { StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.ERROR); accessor.setMessage(ex.getMessage()); accessor.setLeaveMutable(true); StompHeaderAccessor clientHeaderAccessor = null; if (clientMessage != null) { clientHeaderAccessor = MessageHeaderAccessor.getAccessor(clientMessage, StompHeaderAccessor.class); if (clientHeaderAccessor != null) { String receiptId = clientHeaderAccessor.getReceipt(); if (receiptId != null) { accessor.setReceiptId(receiptId); } } } return handleInternal(accessor, EMPTY_PAYLOAD, ex, clientHeaderAccessor); }
@Override @Nullable public Message<byte[]> handleClientMessageProcessingError(@Nullable Message<byte[]> clientMessage, Throwable ex) { StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.ERROR); accessor.setMessage(ex.getMessage()); accessor.setLeaveMutable(true); StompHeaderAccessor clientHeaderAccessor = null; if (clientMessage != null) { clientHeaderAccessor = MessageHeaderAccessor.getAccessor(clientMessage, StompHeaderAccessor.class); if (clientHeaderAccessor != null) { String receiptId = clientHeaderAccessor.getReceipt(); if (receiptId != null) { accessor.setReceiptId(receiptId); } } } return handleInternal(accessor, EMPTY_PAYLOAD, ex, clientHeaderAccessor); }
@Override public String getShortLogMessage(Object payload) { StompCommand command = getCommand(); if (StompCommand.SUBSCRIBE.equals(command)) { return "SUBSCRIBE " + getDestination() + " id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.UNSUBSCRIBE.equals(command)) { return "UNSUBSCRIBE id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.SEND.equals(command)) { return "SEND " + getDestination() + appendSession() + appendPayload(payload); } else if (StompCommand.CONNECT.equals(command)) { Principal user = getUser(); return "CONNECT" + (user != null ? " user=" + user.getName() : "") + appendSession(); } else if (StompCommand.CONNECTED.equals(command)) { return "CONNECTED heart-beat=" + Arrays.toString(getHeartbeat()) + appendSession(); } else if (StompCommand.DISCONNECT.equals(command)) { String receipt = getReceipt(); return "DISCONNECT" + (receipt != null ? " receipt=" + receipt : "") + appendSession(); } else { return getDetailedLogMessage(payload); } }
@Override public String getShortLogMessage(Object payload) { StompCommand command = getCommand(); if (StompCommand.SUBSCRIBE.equals(command)) { return "SUBSCRIBE " + getDestination() + " id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.UNSUBSCRIBE.equals(command)) { return "UNSUBSCRIBE id=" + getSubscriptionId() + appendSession(); } else if (StompCommand.SEND.equals(command)) { return "SEND " + getDestination() + appendSession() + appendPayload(payload); } else if (StompCommand.CONNECT.equals(command)) { Principal user = getUser(); return "CONNECT" + (user != null ? " user=" + user.getName() : "") + appendSession(); } else if (StompCommand.CONNECTED.equals(command)) { return "CONNECTED heart-beat=" + Arrays.toString(getHeartbeat()) + appendSession(); } else if (StompCommand.DISCONNECT.equals(command)) { String receipt = getReceipt(); return "DISCONNECT" + (receipt != null ? " receipt=" + receipt : "") + appendSession(); } else { return getDetailedLogMessage(payload); } }