Search code examples
springspring-mvcwebsocketspring-websocketspring-4

Spring WebSocket - notifying subscribers is not working


I'm trying to get Spring Websockets (Spring 4) to work in the project that I've been working on. So far I have opening Websocket, adding subscribers and sending messages.

Since yesterday I've been trying to figure out why my endpoint doesn't process the message that is being send by stomp client included in my HTML. There's actually no error in the console as well (ok, I'm not 100% sure what "connected to server undefined" here means).

Here's output from Chrome console:

Opening Web Socket...
Web Socket Opened...

>>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000

<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:[email protected]

connected to server undefined

Connected: CONNECTED
user-name:[email protected]
heart-beat:0,0
version:1.1


>>> SUBSCRIBE
id:sub-0
destination:/my-project/notify-open-documents/1

Sending message : {"documentId":"1"}

>>> SEND
destination:/my-project/ws/lock-document
content-length:19

{"documentId":"1"}

and here's my code:

Configuration:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/notify-open-documents");
        registry.setApplicationDestinationPrefixes("/ws");   
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/lock-document");
        stompEndpointRegistry.addEndpoint("/lock-document").withSockJS();
    }
}

The controller:

@Controller
public class DocumentWebsocketController {

    @MessageMapping("/lock-document")
    @SendTo("/notify-open-documents/{id}")
    public Response response(@DestinationVariable("id") Long id, Message message) {
        return new Response(message.getDocumentId());
    }
}

and STOMP related part of my HTML:

<script type="text/javascript">

    $(document).ready(function() { 
        connect(); 
    });

    var stompClient = null;

    function connect() {
        var socket = new SockJS('<spring:url value="/lock-document"/>');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('<spring:url value="/notify-open-documents/${id}"/>', function (messageOutput) {
                console.log('Receiving message: ' + JSON.parse(messageOutput.body));
            });
            sendName();
        });
    }

    function disconnect() {
        if (stompClient !== null) {
            stompClient.disconnect();
        }
        console.log("Disconnected");
    }

    function sendName() {
        console.log("Sending message : " + JSON.stringify({'documentId' : "${id}" }));
        stompClient.send('<spring:url value="/ws/lock-document"/>', {}, JSON.stringify({'documentId': "${id}"}));
    }

</script>

I'm really running out of ideas what might be wrong, my browser supports WebSockets, from what I see in logs, WebSocket is being open properly, the message is being send, but what I can't figure out is why my Controller is unable to process the incoming messages.


Solution

  • From your HTML snippet I see you are using the spring:url tag to generate STOMP destinations. The spring:url tag adds the context path which doesn't make sense for a STOMP destination.

    The application destination prefix you are configuring is /ws and the broker destination prefix /notify-open-documents, none of these will match your context path which is /my-project (from your console output). Remove the context path from your subscription destinations and when sending messages (not from the SockJS URL):

    stompClient.send('/ws/lock-document', {}, JSON.stringify({'documentId': "${id}"}));