Apache ActiveMQ Artemis

En este artículo vamos a hablar sobre una herramienta muy popular para la comunicación entre aplicaciones llamada Apache ActiveMQ Artemis, además revisaremos un ejemplo de cómo implementar su funcionamiento utilizando dos microservicios implementados con Spring Boot y Java.

A menudo, nos encontramos con eventos que suceden en nuestros sistemas y necesitamos que otros sistemas se enteren de ellos. Notificar estos eventos de manera síncrona puede generar problemas de rendimiento y disponibilidad, ya que los sistemas dependen de la respuesta inmediata de otros sistemas. En cambio, hacerlo de manera asíncrona presenta varias ventajas, como la reducción de la dependencia y el acoplamiento entre sistemas, mejorando la eficiencia y la escalabilidad de nuestras aplicaciones.

A veces, incluso tenemos procesos manuales que requieren la intervención de una persona para realizar acciones en respuesta a un evento. Con la ayuda de Apache ActiveMQ Artemis, podemos conectar nuestras aplicaciones de manera más eficiente y eliminar estos procesos manuales que no generan valor a nuestros negocios. Este tipo de productos, conocidos como MOM (Message Oriented Middleware), nos permiten implementar el asincronismo, facilitando la comunicación entre sistemas de una manera más flexible y robusta.

Artemis

Comenzamos hablando sobre qué es ActiveMQ Artemis.

En términos oficiales, Apache ActiveMQ Artemis es un intermediario que facilita la comunicación entre diferentes sistemas o aplicaciones. Es de código abierto, muy popular y multiprotocolo, basado en Java. Artemis permite integrar aplicaciones multiplataforma utilizando diversos protocolos, como AMQP (Advanced Message Queuing Protocol – Protocolo Avanzado de Cola de Mensajes), JMS, MQTT, STOMP, OpenWire, entre otros. Gracias a esta variedad de protocolos, Artemis es una excelente opción para tener comunicación entre dos aplicaciones y poder pasar información de un sistema a otro cuando ocurre un evento.

Arquitectura

La estructura utilizada es un Middleware Orientado a Mensajes (MOM), el cual permite la comunicación a través del intercambio de mensajes de forma asíncrona. Esto significa que las operaciones se llevan a cabo sin requerir que todas las partes involucradas en la comunicación estén disponibles al mismo tiempo que ocurre el envío de eventos, permitiendo así que los procesos continúen su ejecución sin esperar una respuesta inmediata.

Flujo de Mensajes entre Producer y Consumer con ActiveMQ Artemis

En Artemis contamos con dos tipos de envío de mensajes: los mensajes que se envían a colas de tipo anycast y los de tipo multicast.

Anycast: Conocido como punto a punto (Point-to-Point), en este tipo de cola, varios consumidores están a la escucha de la misma cola y van leyendo los mensajes a medida que llegan. Sin embargo, no todos los consumidores pueden leer el mismo mensaje al mismo tiempo.

Envío de Mensaje Anycast en ActiveMQ Artemis

Multicast: Es un modo de distribución de tipo publicación-suscripción (pub/sub). Cada mensaje que se envía a una dirección de tipo multicast se replica a las colas que contienen cada sistema que esté a la escucha de los mismos. Como se muestra en la gráfica, aquí tenemos dos consumidores y ambos se enterarán del mismo mensaje al mismo tiempo.

Envío de Mensaje Multicast en ActiveMQ Artemis

Para el desarrollo de este blog, se trabajará con colas de tipo anycast.

La versión que utilizaremos de ActiveMQ Artemis será la última hasta la fecha de este blog, que es la 2.35. Podemos buscarla en DockerHub como se puede observar en la imagen.

ActiveMQ Artemis en DockerHub

Spring Boot

Para este blog vamos a trabajar con microservicios de Spring Boot, utilizaremos Maven y el lenguaje Java. La última versión de Spring Boot hasta la fecha de este blog es 3.3.1, y la versión de Java es 21. Agregaremos ActiveMQ Artemis a los proyectos. Los proyectos tienen el nombre de «producer» y «consumer». El producer es el encargado de enviar el mensaje a Artemis y crear la cola en Artemis, y el consumer es el encargado de suscribirse a esa cola y leer los mensajes que envíe el producer.

Creación de Proyecto en Spring Initializr para Producer
Creación de Proyecto en Spring Initializr para Consumer

Escenario a Resolver

En un hospital, hay dos sistemas involucrados en la gestión de camas que funcionan de la siguiente forma:

Para desarrollar este requerimiento, los proyectos que creamos en Spring Boot serán: el producer como nuestro Sistema A y el consumer como nuestro Sistema B.

En el proyecto que creamos en Spring, al agregar la dependencia de Docker y ActiveMQ Artemis, se genera un archivo compose.yaml. Utilizaremos este archivo para levantar nuestro contenedor de Artemis. En el proyecto producer, como es el que va a generar el evento, editaremos el archivo compose.yaml, añadiendo la siguiente información:

Configuración YAML para Levantar ActiveMQ Artemis en Docker

Para levantar el contenedor de Artemis con las modificaciones realizadas al archivo compose.yaml, en este blog se ejecutará con Podman porque la práctica se está realizando en un sistema operativo Fedora, que ya lo incluye. Pero si cuentan con Docker también pueden utilizarlo, no habría problema. Ejecutamos nuestro archivo desde la ubicación donde se encuentra nuestro archivo compose.yaml y ejecutamos:

podman-compose -f compose.yaml up 

o con Docker:

docker compose -f compose.yaml up

Esto comenzará a descargar la imagen de Artemis.

Descarga de Imagen de ActiveMQ Artemis
Contenedor de ActiveMQ Artemis Levantado

Una vez que en los logs salga un mensaje como el siguiente: AMQ241004: Artemis Console available at link, podemos ingresar a un navegador y acceder a la URL localhost:8161 para acceder a la pantalla de Artemis.

Pantalla de Logueo de ActiveMQ Artemis en Navegador

Las credenciales serán las que configuramos en nuestro archivo compose.yaml, en este caso artemis como username y artemis como password.

Una vez dentro de la consola, podemos observar las versiones de Artemis y navegar por el mismo.

Versión de ActiveMQ Artemis
Pantalla de Inicio de ActiveMQ Artemis

Se debe deshabilitar el Docker Compose de los proyectos Spring Boot, en el archivo de propiedades application.properties colocar:

spring.docker.compose.enabled=false

Para que no se levante Artemis cada que se ejecute el proyecto, sino que se levante una única vez cuando nosotros lo necesitemos.

Para poder enviar el evento desde el Sistema A al Sistema B, necesitamos un método que nos ayude con el envío. En este caso, hemos creado el método pushRequestPaymentOrder (puedes darle cualquier nombre). Primero, creamos nuestro DTO que contendrá la información que necesita el Sistema B. Para nuestro caso planteado, vamos a enviar un mensaje que indique que la cama está disponible y el ID de la cama correspondiente.

Utilizamos el atributo de clase que inyectamos de JmsTemplate, una clase de Spring que facilita el envío y recepción de mensajes a través de JMS. Utilizamos el método convertAndSend, que convierte el objeto DTO en un mensaje en formato JSON y lo envía a TopicDemo, que es el nombre de la cola a la que se envía el mensaje.

El método pushRequestPaymentOrder se llama desde la lógica de negocio en el sistema cuando se necesita encolar información. Por ejemplo, cuando se detecta que una cama está disponible, se invoca este método para enviar la información al Sistema B.

Programación para Encolar Mensajes en ActiveMQ Artemis

Para que podamos observar la información de ese mensaje en Artemis, debemos tener en nuestro producer lo siguiente:

Método de Transformación a JSON antes de Encolar en ActiveMQ Artemis

El convertidor se utiliza tanto en el productor como en el consumidor para manejar la transformación del DTO. En el Sistema A, el convertidor transforma el DTO de un objeto Java a JSON antes de enviarlo a Artemis. Luego, cuando consumimos el evento en el Sistema B, el convertidor transforma el JSON almacenado en Artemis de vuelta a un objeto Java. Esto asegura que los datos se mantengan consistentes y fácilmente manejables a lo largo del proceso de comunicación entre sistemas.

Confirmación de Llegada de Mensaje en ActiveMQ Artemis
Detalle del Mensaje en ActiveMQ Artemis

Una vez confirmado que nuestro evento llegó con normalidad a Artemis y podemos observar su información, lo siguiente es levantar nuestro Sistema B, que en este caso sería nuestro consumidor. Debemos configurarlo para que esté a la escucha de los eventos que lleguen a una cola específica para poder leerlos y acceder a su información.

Eso lo realizamos de la siguiente manera:

Programación para Consumir un Mensaje de una Cola en ActiveMQ Artemis

Creamos nuestro método que tiene la etiqueta @JmsListener, que indica que está a la escucha de lo que llegue a esa dirección de cola, llamada TopicDemo, que es el nombre de la cola donde el producer envió el evento. Pero como se mencionó anteriormente, al momento de leer el evento, está leyendo un valor tipo JSON, por lo que queremos que lo transforme al objeto que necesitamos. Para ello, aquí también utilizamos el método jacksonJmsMessageConverter.

Método para Consumir Mensaje y Transformación de JSON a Objeto

Como podemos ver en los logs, al levantar este microservicio se hará el consumo del mensaje que representa el evento. Ya tenemos que la cama está disponible, y lo siguiente sería actualizar en el Sistema B, en base de datos, que ahora la cama con el ID que acabamos de leer está disponible.

Resumen

En resumen, teníamos un Sistema A que contaba con una información, pero esa información necesitaba saberla el Sistema B. Para que el Sistema B se enterara, era necesario contar con una persona que analizara los cambios en el Sistema A y luego actualizara el Sistema B. Pero, ¿Qué ocurre si durante el almuerzo hay cambios o si la persona encargada de actualizar se distrae? No contaremos con la información actualizada en tiempo real.

Comunicación entre Sistema A y B a través de una Persona

Para eso, presentamos la solución planteada en este Blog: ahora no se requiere de una persona para hacer estas actualizaciones, sino que el Sistema A será un producer que envía eventos a Artemis cuando se desocupe alguna cama. Luego, el Sistema B será un consumer que esta a la escucha de esos eventos en Artemis para leerlos y actualizar automáticamente en sus registros que ahora la cama está disponible, asegurando así información actualizada en todo momento.

Comunicación entre Sistema A y B a través de ActiveMQ Artemis

Esto fue un ejemplo con el uso de colas de tipo anycast. Próximamente se hará un blog con un escenario para colas de tipo multicast.

Si tienes alguna pregunta o comentario sobre este tema, no dudes en dejarlos abajo. Nos encantaría saber tu opinión y ayudarte con cualquier duda que puedas tener. ¡Gracias por leer!

¿Quieres mejorar tus procesos de integración?

Descubre nuestros servicios y agenda una demo.

leave a comment