Mam do zaimplementowania taki flow w Spring Gateway
- pobieram jakis rekord z bazy danych
- jezeli ten rekord istnieje, jest z nim zwiazana jakas logika biznesowa, ktora w jednym z przypadkow moze zakonczyc sie tym np. zwracam jakis error
- jezeli ten rekord nie istnieje to nie robie nic, po prostu wolam kolejny filtr
Wyglada to w ten sposob, logika w doSomethingIfDbHasResult
jest calkowicie przypadkowa, w rzeczywistosci tutaj dzieje sie x innych rzeczy
GatewayFilter gatewayFilterImpl() {
return ((exchange, chain) ->
queryDb()
.flatMap(res -> doSomethingIfDbHasResult(exchange, res))
.switchIfEmpty(doNothingIfDbHasNoResults(exchange, chain)));
}
private Mono<String> queryDb() {
return Mono.just("Some string from reactive DB - this may be Mono.empty() as well");
}
private Mono<Void> doSomethingIfDbHasResult(ServerWebExchange exchange, String dbResult) {
exchange.getResponse().setStatusCode(HttpStatus.CONFLICT);
exchange.getResponse().getHeaders().add("x-custom-header", dbResult);
return exchange.getResponse().setComplete();
}
private Mono<Void> doNothingIfDbHasNoResults(ServerWebExchange exchange, GatewayFilterChain chain) {
return Mono.defer(() -> chain.filter(exchange));
}
Niestety, powyzszy kod nie dziala tak jak chce. Gdy w bazie faktycznie brakuje danego rekordu, to od razu lecimy do switchIfEmpty
i jest ok, jezeli jednak w bazie jest ren rekord, odpala sie zawartosc flatMap
- to jest ok, ale rezultatem jest znow Mono<Void>
, poniewaz tego wymaga GatewayFilter
. W efekcie, switchIfEmpty
i tak sie uruchamia co jest oczywiscie niepozadane w tym przypadku.
Pytanie wiec, jak to obsluzyc?
Jezeli wynik z bazy danych nie bylby reaktywny, to zrobilbym po prostu
return ((exchange, chain) ->
Optional.ofNullable("Query DB result")
.map(res -> doSomethingIfDbHasResult(exchange, res))
.orElseGet(() -> doNothingIfDbHasNoResults(exchange, chain)));
Niestety nie wiem jak takie cos osiagnac w przypadku Mono