41

Is there a way to use WebSockets with SockJS client and Spring 4 server but not using STOMP?

Based on this tutorial from Spring's website, I know how to set up a WebSocket based application using Stomp and Spring 4. On the client side, we have:

     var socket = new SockJS('/hello');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/greetings', function(greeting){
                showGreeting(JSON.parse(greeting.body).content);
            });
        });

And on the server side, we have the following in the controller:

@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
    Thread.sleep(3000); // simulated delay
    return new Greeting("Hello, " + message.getName() + "!");
}

Now, I understand that @MessageMapping("/hello") ensures that if a message is sent to a destination "/hello", then the greeting() method will be called. And since the stompClient is subscribed to "/topic/greetings", the @SendTo("/topic/greetings") will send the message back to the stompClient.

But the problem with the above is that stompClient is a Stomp object. And I want to simply use sock.send('test'); and have it delivered to my server's destination. And I want to do @SendTo("myownclientdestinationmap"), I can receive it by

sock.onmessage = function(e) {
     console.log('message', e.data);
 };

So, any way to do this with Spring 4, SockJS and without Stomp? Or does Spring 4 WebSocket only supports Stomp?

BlueChips23
  • 1,861
  • 5
  • 34
  • 53
  • I want to use WebSocket in my `spring-mvc` application, could you please guide/tell me why you don't want to use `STOMP` ?, thank you !!! – Shantaram Tupe Nov 24 '17 at 07:59

1 Answers1

65

Spring supports STOMP over WebSocket but the use of a subprotocol is not mandatory, you can deal with the raw websocket. When using a raw websocket, the message sent lacks of information to make Spring route it to a specific message handler method (we don't have any messaging protocol), so instead of annotating your controller, you'll have to implement a WebSocketHandler:

public class GreetingHandler extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        Thread.sleep(3000); // simulated delay
        TextMessage msg = new TextMessage("Hello, " + message.getPayload() + "!");
        session.sendMessage(msg);
    }
}

And then add your handler to the registry in the configuration (you can add more than one handler and use SockJS for fallback options):

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(greetingHandler(), "/greeting").withSockJS();
    }

    @Bean
    public WebSocketHandler greetingHandler() {
        return new GreetingHandler();
    }
}

The client side will be something like this:

var sock = new SockJS('http://localhost:8080/greeting');

sock.onmessage = function(e) {
    console.log('message', e.data);
}
Mateusz Szulc
  • 1,734
  • 19
  • 18
Sergi Almar
  • 8,054
  • 3
  • 32
  • 30
  • 1
    hello @Sergi Almar ,I have one question here ,using spring 4 is it possible to connect to web socket using `new WebSocket('ws://localhost:8080/my-app/ws-connect-url');`? – Dev May 27 '15 at 11:09
  • 3
    Sure, just remove the .withSockJS(); from the configuration and use the plain JS WebSocket API (you won't have any fallback options) – Sergi Almar May 27 '15 at 11:20
  • 2
    This answer works great, but I now I wonder: is it possible in this setup to broadcast a message to all connected clients? It is straightforward in plain JSR356 websockets, so I hope it is doable here too. – TMG Nov 24 '15 at 23:44
  • 1
    Created a separate question from my last comment: http://stackoverflow.com/q/33910639/4358405 – TMG Nov 25 '15 at 08:30
  • 2
    It doesn't work for me using it without .withSockJS() -> can't connect using "ws://localhost....", could you help? I'm using spring boot – Greyshack Dec 13 '15 at 09:30
  • Websocket client doesn't work with Spring boot 1.3.2 with authentication.http://stackoverflow.com/questions/35332080/spring-boot-authentication-with-tyrus-websocket-client-causes-authenticationexce – myspri Feb 11 '16 at 07:02
  • @SergiAlmar could u please help me for [How to properly configure Stomp and SockJS endpoint in Spring MVC?](https://stackoverflow.com/q/47551224/3425489) – Shantaram Tupe Nov 29 '17 at 12:30