Programación Reactiva en Java: Biblioteca Reactor

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Programación Reactiva en Java con Project Reactor



La programación reactiva es un paradigma de desarrollo orientado a flujos de datos asíncronos y la propagación de cambios. En Java, este concepto se implementa a través de la especificación Reactive Streams y su implementación más popular: la biblioteca Project Reactor (parte del ecosistema Spring WebFlux).



A diferencia del código imperativo tradicional, donde el programa ejecuta comandos secuencialmente, el enfoque reactivo permite procesar datos a medida que llegan, sin bloquear los hilos de ejecución. Esto es especialmente importante para sistemas de alta carga, microservicios y aplicaciones con un gran número de solicitudes concurrentes.



Componentes principales de Reactor



La biblioteca proporciona dos tipos principales de secuencias reactivas:



  • Mono<T> — representa un flujo que puede contener 0 o 1 elemento. Se utiliza para operaciones asíncronas individuales (por ejemplo, una solicitud HTTP, obtener un registro de la base de datos).
  • Flux<T> — representa un flujo que puede contener de 0 a N elementos. Es adecuado para colecciones, flujos de eventos o datos que llegan en partes.


Ambos tipos implementan la interfaz Publisher de la especificación Reactive Streams y admiten el mecanismo de backpressure (contrapresión): la capacidad del suscriptor para controlar la velocidad de recepción de datos.



Ejemplo: creación y procesamiento de Flux



Veamos un ejemplo simple de creación de un flujo reactivo de números y su procesamiento:



import reactor.core.publisher.Flux;

public class ReactorExample { public static void main(String[] args) { Flux<Integer> numbers = Flux.just(1, 2, 3, 4, 5);

numbers .map(n -> n * 2) // transformación .filter(n -> n % 3 == 0) // filtrado .subscribe( data -> System.out.println("Recibido: " + data), error -> System.err.println("Error: " + error), () -> System.out.println("¡Completado!") ); }}


En este ejemplo:

  • Flux.just() crea un flujo de cinco números.
  • map() multiplica cada elemento por 2.
  • filter() conserva solo los números múltiplos de 3.
  • subscribe() inicia el procesamiento: muestra el resultado, maneja errores y señala la finalización.


Asincronía y trabajo con Mono



Reactor permite realizar operaciones asíncronas sin bloquear hilos. Por ejemplo, la simulación de una solicitud a un servicio remoto:



import reactor.core.publisher.Mono;import java.time.Duration;

public class AsyncExample { public static void main(String[] args) throws InterruptedException { Mono<String> asyncResult = Mono.fromSupplier(() -> { try { Thread.sleep(1000); // simulación de retardo } catch (InterruptedException e) { e.printStackTrace(); } return "Datos recibidos"; }).subscribeOn(Schedulers.boundedElastic()); // ejecutar en otro hilo

System.out.println("Solicitud enviada..."); asyncResult.subscribe(System.out::println); Thread.sleep(2000); // esperar a que termine }}


Punto clave: la llamada a .subscribeOn() traslada la ejecución de la operación costosa a un hilo separado, sin bloquear el principal. El suscriptor recibirá el resultado de forma asíncrona.



Manejo de errores en flujos reactivos



A diferencia de try-catch, en la programación reactiva los errores se manejan mediante operadores:



Flux<String> fluxWithError = Flux.just("A", "B", "C")    .map(s -> {        if ("B".equals(s)) t                    

Recommendations