Search code examples
javaspringspring-bootstompspring-websocket

STOMP header on @MessageMapping return


In my Spring Boot 1.5 application with Spring Websocket, I'd like to set a custom STOMP header on the return value of a @MessageMapping method, but I don't know how to do this. For example:

@Controller
public class ChannelController {

    @MessageMapping("/books/{id}")
    public Book receive(@DestinationVariable("id") Long bookId) {
        return findBook(bookId);
    }

    private Book findBook(Long bookId) {
        return //...
    }
}

When receive is triggered from a client's STOMP SEND, I'd like the STOMP MESSAGE reply frame with the book body to have a custom header: message-type:BOOK like this:

MESSAGE
message-type:BOOK
destination:/topic/books/1
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:0-7
content-length:1868

{ 
  "createdDate" : "2017-08-10T10:40:39.256", 
  "lastModifiedDate" : "2017-08-10T10:42:57.976", 
  "id" : 1, 
  "name" : "The big book", 
  "description" : null 
}
^@

How do I set a STOMP header for the reply return value in a @MessageMapping?


Solution

  • If the return value signature is not important, you can use SimpMessagingTemplate as @Shchipunov noted in the comments to his answer:

    @Controller
    @AllArgsConstructor
    public class ChannelController {
    
        private final SimpMessagingTemplate messagingTemplate; 
    
        @MessageMapping("/books/{id}")
        public void receive(@DestinationVariable("id") Long bookId, SimpMessageHeaderAccessor accessor ) {
            accessor.setHeader("message-type", "BOOK");
    
            messagingTemplate.convertAndSend(
                "/topic/books/" + bookId, findBook(bookId), accessor.toMap()
            );
        }
    
        private Book findBook(Long bookId) {
            return //...
        }
    }
    

    which does correctly serialize to the MESSAGE frame in the question.