Que es WebFlux y como nos ayuda a hacer más fácil la programación reactiva con SpringBoot.
WebFlux es un framework parte de Spring 5 que está basado en Project Reactor el cual nos ofrece anotaciones para poder implementar aplicaciones reactivas. WebFlux es una alternativa al tradicional Spring MVC ampliamente usado hasta hoy. WebFlux nos ofrece las siguientes características.
• Non_blocking thread: los hilos que pueden trabajar de manera concurrente sin tener que esperar a la tarea previa.
• Reactive Stream API: Nos ofrece la posibilidad de crear streams asíncronos que no son bloqueantes.
• Asyncronus data processing: Permite procesar la data de manera asíncrona sin interrumpir la ejecución de la aplicación principal.
Con WebFlux se pueden crear dos formas de implementaciones reactivas, una mediante anotaciones de SpringBoot en el controlador muy similar al conocido y clásico Spring MVC, pero ahora haciendo uso de los streams reactivas Flux y Mono y la segunda es mediante programación funcional haciendo uso de “functional routing and Handling”. La gran diferencia está en que la segunda esta activa desde que se inicia la aplicación hasta que esta es finalizada y no requiere decirle a la aplicación mediante anotaciones donde tiene que manejar las solicitudes como se hace usualmente con la anotación @RestController en el clásico Spring MVC.
• Ahora empecemos con la parte práctica:
Para esto usaremos “spring initializr” en el cual crearemos el proyecto y seleccionaremos las siguientes dependencias.
Para esta parte técnica usaremos una sola entidad para hacer más entendible como hacer una API usando Flux y Mono. La entidad será “Book” y tiene la siguiente estructura:
• La tabla
Para efectuar las operaciones sobre la base de datos creamos el repositorio con la ayuda de R2DBC, esto nos ayudara a hacer consultas sobre la base de datos y se crea de la siguiente manera:
A diferencia del clásico “JpaRepository” ahora se debe extender “ReactiveCrudRepository”.
Ahora creamos los EndPoint, para este ejemplo crearemos tanto los clásicos EndPoint usando la estructura de Spring MVC, pero también haremos estos EndPoint usando programación funcional los cuales hacen uso de las funciones “Router” y una clase “Handler” que manejara las solicitudes recibidas en el router.
Haciendo uso de la manera clásica Spring MVC tenemos lo siguiente:
• Service
La capa “Service” para manejar la lógica del negocio.
• El “Controller”:
Cabe destacar que en estos EndPoint para que se pueda observar en el navegador que es no bloqueante es importante que se especifique “MediaType.TEXT_EVENT_STREAM_VALUE”.
Ejemplo de cómo se ve el log y el navegador al usar el EndPoint "/reactive/api/books/”
En el navegador se verá algo como esto:
Y el log muestra lo siguiente:
• Se puede observar cómo los pasos de los stream reactivos trabajan, primero haciendo “onSubscribe”, luego la solicitud “request” y después uno a uno va devolviendo los datos en “onNext” y finalmente se ejecuta “onComplete” cuando el evento finaliza.
Ahora veamos cómo se hace de forma funcional.
• Router
El” Router” es el equivalente a la capa controller en el modelo clásico Spring MVC. Para indicarle a “SpringBoot “ que este es un Router es necesario usar la anotación “@Configuration” para que Spring lo incluya en su autoconfiguración al iniciar la aplicación. Luego cada función “RouterFunction” que contenga rutas es importante marcarlo con “@Bean” para que SpringBoot lo inyecte en la configuración como un recurso disponible para la aplicación.
Haciendo uso de esta nueva forma se definen las mismas rutas usadas anteriormente, pero agregándoles “func” para diferenciar una de otra.
• Handler
El “Handler” es el encargado de manipular la petición hecha y enrutada. El “handler” se puede usar como el “service” del modelo clásico o también se puede usar para preparar todo lo necesario en la petición y derivarlo al “service” para que haga toda la lógica del negocio, esto depende de cada desarrollador y/o empresa donde se esté trabajando. El Handler se tiene que marcar con “@Component” para que spring detecte el “Bean”;
Se puede observar cómo usar la programación reactiva de Spring Web Flux ayuda a no mantener bloqueado el hilo a la espera de una respuesta de la base de datos, gracias al flujo de eventos de los stream reactivos.
Es importante notar que a diferencia de lo que se puede pensar, este tipo de implementación no hace a la aplicación más rápida, lo que si se logra con este tipo de programación es la disminución de uso de memoria en la aplicación ya que a diferencia del clásico Spring MVC con este tipo de programación no es necesario crear un hilo por petición lo que en el modelo clásico si se tiene una alta concurrencia el uso de memoria se puede disparar.
Otro punto importante a la hora de usar este tipo de programación es que se piense bien donde va ser utilizado ya que para sacar ventaja de este tipo de programación es necesario que todas las partes soporten esta “reactividad” no basta solo con hacer una API reactiva y que todas las demás partes no soporten este tipo de implementación, esto no ofrecerá ningún beneficio.