Notificaciones vía web sockets con Spring Messaging en una aplicación AngularJS

6
10944

Existen muchas técnicas para mantener una conexión bidireccional entre cliente y servidor, en este tutorial vamos a ver como hacerlo con el soporte de Spring en una aplicación AngularJS

0. Índice de contenidos.


1. Introducción

Ya hemos visto como podemos implementar una conexión bidireccional entre cliente y servidor
estableciendo un canal de comunicación en tiempo real con el soporte de Web Sockets y:

En esta entrada haremos uso de la librería spring-websocket desarrollada bajo el proyecto
spring-messaging que es una abstracción sobre el soporte nativo
de web sockets del servidor sobre el cuál arranca nuestra aplicación, de modo tal que podemos seguir desplegando
sobre un Apache Tomcat pero en vez de configurar y registrar de forma nativa la conectividad lo haremos con el
soporte de Spring beneficiándonos de su configurabilidad y el soporte de inyección de dependencias en nuestros
servicios.

Los web sockets son una capa ligera de comunicación sobre TCP que permite el uso de otros protocolos a bajo nivel para encapsular los mensajes; en este tutorial usaremos STOMP desde una aplicación AngularJS para
conectarnos/desconectarnos al servidor y enviar y recibir mensajes.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2.3 GHz Intel Core i7, 16GB DDR3).
  • Sistema Operativo: Mac OS Mavericks 10.9.4
  • Spring 4.1.6.RELEASE
  • Apache Tomcat 8.0.20


3. Configuración.

Como siempre, asumiendo que nuestro proyecto tiene el soporte de maven, lo primero es configurar las dependencias en el pom.xml:

A continuación, podríamos configurar por anotaciones el soporte de web sockets, pero soy un viejuno y prefiero la configuración vía xml:

Con lo anterior estamos habilitando:

  • websocket:message-broker: el soporte de mensajería generíco de spring-messaging para el prefijo de “app”; para remitir un mensaje desde el cliente a un endPoint “chat”, se hará a través de “/app/chat”
  • websocket:stomp-endpoint: registra un endPoint “chat” habilitando SockJS
  • websocket:simple-broker: un sencillo broker de mensajería basado en memoria que registra un “topic”, con ese prefijo, para el transporte de los mensajes a los clientes.

SockJS es una librería Javascript para navegadores que permite el uso de WebSockets orientado a objetos.
SockJS proporciona un api, cross-browser, cross-domain que permite una comunicación entre el navegador y
el servidor de modo tal que si el navegador soporta WebSockets hace uso de la implementación del mismo y, sino lo soporta, lo emula de forma nativa.

Por último, en el descriptor de despliegue web.xml tendríamos que declarar el front controller de spring MVC
con una configuración similar a la siguiente:


4. Creación de un manejador de mensajes.

Con el soporte de spring mvc podemos registrar un controlador de la siguiente forma

Message es un POJO que encapsula como propiedades el texto del mensaje .

El método que mapea la URL “sendMessage”, recibe un mensaje y remite el mismo a la cola de mensajería “topic/messages” a la que se pueden suscribir los clientes al conectarse al socket.

Con todo lo anterior tendríamos la siguiente configuración:

  • “topic/messages” para que los clientes se puedan suscribir y recibir los mensajes de saludo del servidor,
  • “app/chat” para que los clientes puedan enviar sus mensajes
  • el prefijo de los recursos anteriores será el contexto de la aplicación + la url-pattern de la declaración del servlet.


5. Soporte de STOMP en AngularJS.

En este punto tenemos dos opciones:

  • buscar un módulo mantenido por un tercero que nos de soporte de STOMP en el cliente, como muchas otras librerías que usamos,
  • implementar nuestro propio servicio de conexión, suscripción y envio de mensajes.

Vamos a optar por la segunda opción puesto que en pruebas de concepto anteriores hemos podido comprobar que
el soporte del modulo “angular-stomp” prevé la conectividad por ws:/ pero no soporta la conexión por http:// y
además queremos tener más control y así comprobamos como crear nuestro propio servicio en AngularJS.

Lo primero es añadir las dependencias de las librerías que nos van a proporcionar el soporte de web sockets y el protocolo de comunicaciones;
si para la parte servidora/java declarábamos las dependencias en el pom.xml de maven, nuestro proyecto de cliente/javascript está gestionado por bower
con lo que debemos añadir las siguientes dependencias a nuestro bower.json

Con ello ya podemos hacer uso de la librería de socksJS para implementar nuestro servicio dentro de un módulo de prueba “pushApp”:

En esta implementación inicial nos hemos basado en la librería que comentabamos pero modificando el prototipado y
el modo en el que se crea el cliente para permitir la conexión vía http.
Al no basarse en promesas propaga los cambios al ámbito $rootScope con la función $apply.

Para hacer uso de la librería bastaría con inyectarla en un controlador:

Y desde el html podríamos tener un código como el siguiente para enviar mensajes y recibirlos,
tanto los nuestros como los de otros clientes.

A nivel de interfaz deberíamos ver algo como lo siguiente:



6. Referencias.


7. Conclusiones.

Hemos visto una aproximación adicional a las que ya proponiamos con web sockets haciendo uso además de un servicio en Angular.

Vale que no aún no tenemos un chat al uso, solo enviamos y recibimos mensajes a todos los usuarios conectados, pero no se puede tener todo en una primera aproximación.

Stay tuned!

Un saludo.

Jose

6 Comentarios

  1. Hola, primero felicitarte por el excelente Post.
    Tengo una duda seria posible por ejemplo enviar un mensaje desde el servidor a los clientes a tráves del web socket según un evento propio del servidor, me refiero a que si por ejemplo tengo mi maquina servidor conectada a una placa arduino y cuando esta me de cierta información yo la comunique a todos mis clientes web.

Dejar respuesta

Please enter your comment!
Please enter your name here