Eventos con Springboot

0
4495

Introducción

Los eventos nos permiten hacer que nuestra aplicación sea más flexible y desacoplada que si usaramos invocaciones a métodos directamente. Esto se hace registrando oyentes para los distintos eventos y, además, puede haber múltiples oyentes por evento.
Springboot ofrece una serie de herramientas para usar el patrón Observer sin tener que hacer ninguna configuración específica y a través de anotaciones.
Como ejemplo vamos a gestionar eventos con Springboot en la que se creen cursos. Cuando un curso sea creado se va a crear un evento y un consumidor de ese evento va a mostrar por consola el título del curso.

Indice

  1. Definiendo los eventos
  2. Publicando
  3. Escuchando
  4. Probando el ejemplo
  5. Soporte a transacciones
  6. Métodos asíncronos
  7. Referencias

Definiendo los eventos

Los eventos deben extender la clase ApplicationEvent.

Ahora bien, para hacernos las cosas más fáciles, si no extendemos de esta clase Spring de forma automática envolverá nuestro objeto en un PayloadApplicationEvent. Esta es la forma que se va a usar en este tutorial.

Publicando eventos

Para publicar eventos se emplea la interfaz ApplicationEventPublisher, que se introduce en un campo de la clase encargada de publicar los eventos. Spring se va a encargar de inyectar esta dependencia al instanciar CoursePublisher.

El método publish es el encargado de publicar el evento del curso.

 Escuchando eventos

Un evento puede tener varios oyentes en distintos puntos de la aplicación, en función de la lógica de negocio. Es Spring el que se encarga de registrar los oyentes al iniciar la aplicación.
Hay dos formas de escuchar un evento: mediante anotaciones con @EventListener o implementando la clase ApplicationListener nosotros mismos. ApplicationListener define un único método, onApplicationEvent, que se llama cuando un evento es lanzado.

Usando la anotación @EventListener hace que sea Spring el que registre un ApplicationListener para el evento concreto. La anotación de @Component está para que Spring lo detecte como Bean para luego inyectarlo donde sea necesario.

Probando el ejemplo

Para probar todo esto se puede crear un pequeño test que levante el contexto de Spring y ejecutarlo. Es necesario levantar el contexto para que se inyecten las dependencias de los @Autowired.

Las anotaciones usadas sobre la clase son: @RunWith que proporciona funcionalidad para los tests y @SpringBootTest que levanta el contexto de Spring. Al correr el test se observará en la consola el mensaje que CourseConsumer tiene definido.

Soporte a transacciones

Mediante el uso de la anotación @TransactionalEventListener se consigue un oyente que va a tener en cuenta si el evento se encuentra en una transacción. ¿Cuándo se va a ejecutar el método del oyente? Se puede especificar la fase en la que se quiere invocar utilizando el argumento phase. Existen cuatro opciones:

  • AFTER_COMMIT es la opción por defecto. Se invoca una vez el commit ha finalizado de forma exitosa.
  • AFTER_COMPLETION se invoca cuando la transacción se ha completado.
  • AFTER_ROLLBACK se invoca solo si la transacción ha terminado en un roll back.
  • BEFORE_COMMIT se invoca antes de que la transacción haga el commit.

Métodos asíncronos

Spring permite crear y publicar eventos de forma síncrona por defecto. Esto tiene la ventaja de permitir al oyente participar en el contexto de la transacción del evento.

Si queremos un comportamiento asíncrono lo que hay que hacer es anotar el método del Bean que queremos que sea asíncrono con @Async. De este modo ese método se ejecutará en otro hilo y el que llama al método no esperará a recibir una respuesta para seguir con la ejecución. También hay que añadir en la configuración la anotación @EnableAsync.

Vamos a anotar el método de publish como asíncrono. Además se añade una espera de 10 segundos antes de publicar el evento.

En el test hay que incluir otro tiempo (de 11 segundos) de espera para que no se cierre la terminal.

El resultado en la consola es:

No se ha esperado a que el primer publisher termine para llamar al siguiente, si no que ha tenido un comportamiento asíncrono. Como se ha visto, configurar los eventos con Springboot para que sean asíncronos es sencillo.

Referencias

Dejar respuesta

Please enter your comment!
Please enter your name here