Spring WebSockets

Today we take a look at the websockets in Spring. Websockets are used to have real time interaction between 2 systems. Which can be any device that works with HTTP, because if the web technology is not available Spring Websockets will use a different technique (long pooling)to get almost the same result (only a bit slower).

Websockets are often used in combination with messagebrokers like ActiveMQ or RabbitMQ. A combination of these techniques can help us with defining a flow for messages to start processes and tasks within a message driven architecture. This is a useful resource for that.

When we want to make a websocket connection the first thing that happens is that we send an HTTP request where we ask if we can get a socket connection. If that’s accepted we get and HTTP status 101 back and we open a socket connection.

To interact with a messagebroker we create a websocket configuration class that directly or indirectly implements: WebSocketMessageBrokerConfigurer.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.setApplicationDestinationPrefixes("/app") 
           .enableSimpleBroker("/topic", "/queue");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/chat").setHandshakeHandler(new UsernameHandshakeHandler()).withSockJS();
}
  • @EnableWebSocketMessageBroker instantiates a simple in memory message broker and enables the use of message brokers.
  • We set the default prefix to /app, so we can still use normal controllers.
  • We set the prefixes for the simple broker to topic and queue (names come from the book about messaging).
  • We register an endpoint at /chat, so we can receive messages there.
  • We set and HandshakeHandler, because we can’t get access to our user account (Principal) in a socket otherwise. Now we know which socket connection belongs to which user.
  • withSocketJS creates the ability to use sockets, or use a different type of messaging if sockets are not available.

To handle the requests at the endpoint we need an implementation of WebSocketConfigurer.

@Configuration
@EnableWebSocket
public class WebSocketClientConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry 
    webSocketHandlerRegistry) {      
        webSocketHandlerRegistry.addHandler(chatHandler(),"/chat").withSockJS();
    }

    @Bean
    public ChatHandler chatHandler(){
        return new ChatHandler();
    }
}
  • @EnableWebSocket  gives us the ability to tell how to process an socket request at an endpoint.
  • We register an handler for an endpoint in the registerWebSocketHandlers method.

A handler either directly or indirectly implements the WebSocketHandler interface. When using JSON we mostly extend the TextWebSocketHandler. One thing we can do here is keep a list of all the connections to the socket, so they can get events (messages) send (emitted) to them.

public class ChatHandler  extends TextWebSocketHandler{

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private List sessions = new CopyOnWriteArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
        log.info(session.toString() +" added to list");
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        for(WebSocketSession s : sessions){
            s.sendMessage(message);
        }
        log.info("message emitted to all subscribers");
    }
}

To first interact with the chat we have to make a controller to interact with.

@Controller
public class GreetingController {

    @MessageMapping("/chat")
    public String message(String message) throws Exception {
        return message;
    }
}
  • This send the message to the socket waiting for messages at at /chat.
  • @MessageMapping contains information about the message.

This are the basics for messaging with Spring WebSocket.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s