π Tempo di lettura: 2 minuti
Nell'ambito di WebFlux, Γ¨ comune gestire catene di operazioni asincrone. Tuttavia, puΓ² capitare di imbattersi in output particolari come Mono<Mono<Void>>. Un esempio? Supponiamo di avere un metodo startCar(keys) che, date le chiavi di un'auto (sampleCar), l'avvia (cambiandone lo stato da STOPPED a RUNNING) e restituisca un Mono<Void>. Per applicare realmente questo cambiamento di stato, Γ¨ necessario effettuare una sottoscrizione esplicita o implicita del Mono.
π Esempio con subscribe() esplicito
final CarState actualState = Mono.just(carKeys)
.doOnNext(keys -> sampleCar.startCar(keys).subscribe())
.map(keys -> sampleCar.getState())
.block();
assertEquals(CarState.RUNNING, actualState);
β οΈ Attenzione: se avessimo scritto .doOnNext(sampleCar::startCar) senza invocare subscribe(), l'auto non sarebbe effettivamente stata avviata, il Mono<Void> sarebbe rimasto inattivo, l'azione non eseguita e l'assertEquals sarebbe fallito.
π Esempio con sottoscrizione implicita
Alternativamente, Γ¨ possibile effettuare la sottoscrizione in maniera implicita "appiattendo" il Mono<Mono<Void>> in un Mono<Void> con flatMap, che gestisce implicitamente la sottoscrizione, e utilizzando l'operatore then() per concatenare un'operazione successiva al Mono precedente.
final CarState actual = Mono.just(carKeys)
.flatMap(sampleCar::startCar)
.then(Mono.defer(() -> Mono.just(sampleCar.getState())))
.block();
π Visualizzare l'evoluzione dei tipi nella catena
Vediamo nel dettaglio come i tipi si trasformano lungo la pipeline reattiva β utile per capire perchΓ© serve la sottoscrizione e quando si ottiene un Mono<Mono<Void>>:
@Test
void test_subscribe() {
final String licensePlate = "BMT 216A";
final Car sampleCar = new Car(licensePlate);
Mono.just(carKeys) //Mono<String>
.map(sampleCar::startCar) //Mono<Mono<Void>>
.map(Mono::subscribe) //Mono<Disposable>
.map(disposable -> sampleCar) //Mono<Car>
.map(Car::getState) //Mono<CarState>
.doOnNext(actual -> assertEquals(CarState.RUNNING, actual))
.block();
}
π Considerazioni aggiuntive
Mono.defer(() -> Mono.just(...)) Γ¨ utilizzato per differire la creazione del Mono fino al momento della sottoscrizione, assicurando la corretta esecuzione di logica dipendente dallo stato corrente.
Alla prossima pillola! β