#java #spring-webflux #project-reactor
Вопрос:
Мой код выглядит следующим образом
public Mono<Ship> getShip() {
//...
}
public Mono<Car> getCar() {
//...
}
public Mono<ShipAndCar> getCombinedMono() {
Mono<Ship> shipMono = getShip();
Mono<Car> carMono = getCar();
return Mono.zip(shipMono, carMono
(ship, car) -> return new ShipAndCar(ship, car);
}
Как getShip
и getCar
то, и другое, и может возвращать ошибку или пустое моно. Я хотел бы вернуть что-то вроде Mono.error(new Exception("Custom message"))
того, где сообщение зависит от того, какой моно пуст. Как мне это сделать?
Если я добавлю a switchIfEmpty
после Mono.zip, Я бы не знал, какой компонент Mono пуст…
Ответ №1:
Если вы заархивируете их в своем коде, вы можете расширить каждый входной моно с помощью оператора switchIfEmpty следующим образом
var carAndShip = Mono.zip(
Optional.ofNullable(shipMono)
.orElseThrow(() -> new RuntimeException("ship is null"))
.switchIfEmpty(Mono.error(new RuntimeException("ship is empty"))),
Optional.ofNullable(carMono)
.orElseThrow(() -> new RuntimeException("car is null"))
.switchIfEmpty(Mono.error(new RuntimeException("car is empty"))),
ShipAndCar::new
);
Комментарии:
1. Он все равно будет выдавать
NullPointerException
при созданииShipAndCar
, а не исключение RuntimeException 🙁2. если значение pass может быть равно нулю, то вы можете добавить проверку с необязательным значением. Это выглядит немного уродливо, хотя.
3. Вопрос в том , что shipMono или carMono являются Mono.empty (), а не в том, что они являются нулевыми
Ответ №2:
Вы можете использовать сопоставление вспомогательных методов Optional
, чтобы отложить решение о том, что делать, когда значение отсутствует, до более позднего потребителя.
Например, если вы просто хотите по умолчанию указать отсутствующее Ship
, но ошибку в отсутствующем Car
:
package com.example.demo;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.Optional;
public class JavaTest {
@Test
public void nullCarProducesSpecificException() {
Mono<Ship> shipMono = Mono.empty();
Mono<Car> carMono = Mono.empty();
Mono<ShipAndCar> map = Mono.zip(
shipMono.transform(JavaTest::toOptional),
carMono.transform(JavaTest::toOptional))
.map(tuple -> new ShipAndCar(
tuple.getT1().orElse(new Ship("US Default")),
tuple.getT2().orElseThrow(() -> new RuntimeException("Car was missing!!")))
);
StepVerifier.create(map)
.verifyErrorMatches(error ->
error instanceof RuntimeException amp;amp;
"Car was missing!!".equals(error.getMessage())
);
}
private static <T> Mono<Optional<T>> toOptional(Mono<T> mono) {
return mono.map(Optional::of)
.defaultIfEmpty(Optional.empty());
}
}