Crear una Lista con los elementos devueltos por un Mono [SOLUCIONADO]

Transformación de Mono a List en Java

En el ámbito de la programación reactiva en Java, especialmente con el uso de la biblioteca Reactor, es habitual encontrarse con el escenario donde uno necesita tomar valores emitidos por un Mono<Object> y colocarlos dentro de una estructura de datos más familiar, como puede ser una Lista. Este proceso no es siempre intuitivo, dado que el paradigma reactivo nos ofrece una nueva forma de pensar y operar con los flujos de datos.

El objetivo de este artículo es profundizar en cómo se puede conseguir este resultado, detallando cada paso y brindando ejemplos de código aplicables a situaciones cotidianas de desarrollo.

Entendiendo Mono en Reactor

Antes de proceder a la conversión, es fundamental entender qué es un Mono y cómo funciona dentro del contexto de Reactor. Mono es una abstracción que representa un flujo de datos con cero o un solo elemento. En otras palabras, es la versión de Reactor para un resultado que se proveerá eventualmente, pero aún no está disponible en el momento en que se declara.

Esta prevención es esencial porque las operaciones con un Mono son generalmente asíncronas y no bloqueantes. Por lo tanto, transformar un Mono en una lista implica gestionar esta naturaleza asíncrona apropiadamente.

Extracción de Datos de un Mono

Para extraer un objeto de un Mono, se pueden utilizar varias estrategias. Una de las maneras más directas es mediante el método block(), que provoca un comportamiento bloqueante hasta que el valor del Mono está disponible.


Mono<Object> mono = ... // Obtener el Mono
Object value = mono.block(); // Se bloquea hasta obtener el valor

Sin embargo, esta no es una práctica recomendada en aplicaciones reactivas, ya que va en contra de la naturaleza no bloqueante de este paradigma.

Transformando Mono a List de forma Reactiva

En lugar de bloquear, una mejor técnica es transformar el Mono en un Flux, que es otro tipo de abstracción en Reactor que representa un flujo que puede emitir varios elementos. Después de esta conversión, podemos recopilar esos elementos en una lista.


Mono<Object> mono = ... // Obtener el Mono
Mono<List<Object>> monoList = mono.flatMapMany(Flux::just)
                                              .collectList();

El operador flatMapMany es utilizado para convertir un Mono en un Flux, y luego con collectList(), recolectamos todos los elementos en una lista. Note que el operador flatMapMany funciona bien asumiendo que el Mono no está vacío. Si el Mono pudiera estar vacío, sería mejor utilizar flux().collectList() para asegurar la creación de una lista, incluso si está vacía.


Mono<Object> mono = ... // Obtener el Mono
Mono<List<Object>> monoList = mono.flux().collectList();

Manejo de un Mono Vacío

Un caso especial ocurre cuando el Mono está vacío. Si intentásemos convertir un Mono vacío en una lista directamente podríamos terminar con una lista nula, lo cual no es deseable. Para manejar este escenario adecuadamente, Reactor nos ofrece el método defaultIfEmpty().


Mono<Object> mono = ... // Obtener el Mono posiblemente vacío
Mono<List<Object>> monoList = mono.flatMapMany(Flux::just)
                                              .collectList()
                                              .defaultIfEmpty(Collections.emptyList());

En el código anterior, si el Mono está vacío, defaultIfEmpty() proveerá una lista vacía en lugar de nula.

Alternativa usando block()

Si se da el caso de que el contexto sí permite un comportamiento bloqueante, o se está trabajando en una prueba unitaria, podremos usar block() con más libertad. Aquí un ejemplo de cómo obtener una lista sincrónicamente:


Mono<Object> mono = ... // Obtener el Mono
List<Object> resultList = mono.flatMapMany(Flux::just)
                                    .collectList()
                                    .block();

Este código producirá una lista con los elementos del Mono de manera síncrona, pero es importante recordar que esto interrumpe la ejecución y espera a que esté disponible el resultado, lo cual va en contra de la filosofía de ejecuciones no bloqueantes de la programación reactiva.

Testeando la Transformación

Es importante garantizar que nuestro código funcione como se espera. Por ello, realizar tests es una parte crítica del desarrollo. A continuación, se muestra cómo podríamos testear la transformación de Mono a lista usando las herramientas de Reactor Test:


Mono<Object> mono = Mono.just("elemento");
StepVerifier.create(mono.flatMapMany(Flux::just).collectList())
            .expectNext(Arrays.asList("elemento"))
            .verifyComplete();

Con StepVerifier, podemos establecer nuestras expectativas sobre los elementos que deben emitirse y verificar que la secuencia de eventos se complete exitosamente.

Conclusión Estratégica Para el Desarrollo Reactivo

Convertir un Mono en una lista de manera efectiva es una habilidad que puede simplificar significativamente varias operaciones en el contexto de aplicaciones reactivas. Es crucial, sin embargo, no olvidar la naturaleza asíncrona y no bloqueante del paradigma reactivo al tomar estas decisiones de diseño.

Este artículo ha cubierto desde enfoques bloqueantes hasta técnicas reactivas más avanzadas para asegurarnos que podamos manejar nuestras colecciones de datos de una manera que esté alineada con las mejores prácticas de Reactor y la programación reactiva en general.

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad