WebSockets con STOMP y Spring Boot


Muchas veces en los proyectos necesitamos mantener una comunicación constante con el servidor (back end) para realizar peticiones o mostrar información en tiempo real, para eso nos pueden ayudar los WebSockets. En esta entrada vamos a ver mediante un ejemplo como implementar WebSockets con STOMP y Spring Boot.

¿Qué es un Socket?

Un WebSocket es un protocolo de comunicación sobre TCP y bidireccional, entre el navegador y el servidor. Esta comunicación puede durar tanto tiempo como el cliente o servidor decidan, hasta que uno de los dos la cierre.

El caso de uso más práctico suele ser el uso para chats, en el cual mantienes una comunicación abierta constante entre el navegador y el servidor.

WebSockets con Spring Boot
chat con WebSockets

Configuración WebSocket con Spring

Añadir dependencia en Maven

Para comenzar vamos a añadir la siguiente dependencia a nuestro proyecto de Spring Boot.

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

Activar WebSocket en Spring Boot

En el siguiente fragmento de código vamos a activar WebSocket en nuestra aplicación de Spring Boot, a registrar los endpoints mediante el método registerStompEndpoints y realizar la configuración del message broker en el método configureMessageBroker.

En el método registerStompEndpoints, se ha dejado todos los orígenes activo por si se quiere hacer pruebas desde algún cliente de sockets.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

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

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/chat");
    registry.addEndpoint("/chat").withSockJS();
    registry.addEndpoint("/chat").setAllowedOrigins("*");

  }
}

Crear el mensaje

A continuación vamos a crear el mensaje que vamos a recibir, el cual estará formado por dos campos:

@Getter
@Setter
public class Message {

  private String text;
  
  private String name;
  
}

Crear el controlador de los mensajes

Una vez que hemos creado el mensaje vamos a crear el controlador que se encargará de recibir el mensaje, para ello vamos a usar dos anotaciones de Spring @MessageMapping y @SendTo

  @MessageMapping("/status")
  @SendTo("/topic/messages")
  public MessageDto sendMessage(MessageDto message, @Header("simpSessionId") String sessionId) {

   //Do something
    return new MessageDto("Message with text : " + message.getText()
        + " received ", " from " + message.getName());
  }

El método anterior se encontrará en una clase bajo la anotación @RestController o @Controller, y por un lado con la anotación @MessageMapping será el endpoint donde recibe los mensajes y por otro lado los enviará al topic mediante la anotación @SendTo.

Algo más que tener en cuenta, es que cuando recibimos un mensaje guardamos su sessionId para poder saber quién se desconecta, esto se hace mediante el atributo simpSessionId que llega en el Header

Crear Notificación de desconexión del Socket

Por lo general los sockets se van a utilizar para crear un canal de comunicación entre el navegador y el servidor, por lo que será necesario saber cuando el socket se desconecta porque, por ejemplo, cierra el navegador, para ello vamos a hacer uso de la anotación @EventListener de Spring. Esta anotación será invocada cuando reciba un evento de tipo SessionDisconnectEvent.

  @EventListener
  public void onDisconnectEvent(SessionDisconnectEvent event) {

    log.debug("Client with session id {} disconnected", event.getSessionId());

    String sessionId = event.getSessionId();

    //Do something

  }

Conclusión

En este artículo hemos visto como configurar WebSockets con STOMP y Spring Boot. El enfoque de este artículo ha sido desde el lado servidor, para poder probar la aplicación se puede hacer uso de algún cliente como AdvancedRestClient.

Para ver el ejemplo completo lo puedes encontrar en Github.

Otros artículos que te pueden interesar:

Spring Boot con Prometheus y Grafana

SoftDelete con Spring Boot e Hibernate

Open Api 3 con Spring Boot


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *