Umgang mit 500-Fehlercode mithilfe des Abrufs im Webclient
Ich habe einige Dokumentationen und andere Fragen zum Stapelüberlauf zu diesem Thema gelesen, aber ich kann meinen Code anscheinend nicht zum Laufen bringen.
Im Grunde genommen habe ich einen WebClient, der eine POST-Anfrage stellt.
- Wenn der Antwortstatus 200 ist, rufe ich einen anderen Endpunkt mit einem anderen WebClient erneut an. Geben Sie nach dem zweiten Webclient-Aufruf eine Zeichenfolge zurück.
- SONST gebe ich nur einen String von der Methode zurück, z. B. "Bestellung konnte nicht erstellt werden."
Einfach genug. (Dies geschieht alles in einem separaten Thread, nicht im Haupt-Thread.)
Ich habe jedoch festgestellt, dass WebClient eine Ausnahme auslöst, wenn ich einen 500-Fehlercode zurückerhalte. Was ich tun möchte, ist, die Ausnahme zu erfassen und diese ordnungsgemäß zu behandeln und einen String wie "Fehler beim Aufrufen des ersten Endpunkts usw." zurückzugeben.
Das habe ich bisher:
private String generateOrder(ImportedOrderDetails importedOrderDetails)
{
Order requestBody = generateRequestBody(importedOrderDetails);
OrderResponse responseForCreatingOrder = orderWebClient()
.post()
.body(Mono.just(requestBody), Order.class)
.retrieve()
.bodyToMono(OrderResponse.class)
.block();
if (responseForCreatingOrder.getResponseStatus().equals(SUCCESS))
{...other call using different webclient}
else{ return "Error creating order."}
Dies funktioniert gut, wenn der Antwortstatus 200 ist, aber wenn er 500 ist, explodiert er. OrderResponse ist ein benutzerdefiniertes Objekt. orderWebClient()ist nur eine Methode, die einen vorgefertigten WebClient zurückgibt, der die baseUrl und Header usw. enthält.
Ich bin auf Folgendes gestoßen : Spring WebClient - Umgang mit Fehlerszenarien Ich habe versucht, es zu implementieren, konnte aber nicht herausfinden, wo die Blockmethode abgelegt werden soll, da ich immer wieder Folgendes erhalten habe:
reactor.core.Exceptions$ReactiveException: java.lang.Exception
at reactor.core.Exceptions.propagate(Exceptions.java:393)
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:97)
at reactor.core.publisher.Mono.block(Mono.java:1680)
Ich musste meinen Code ein wenig bearbeiten, um die Antwort auf diese Frage umzusetzen:
private Mono<? extends Throwable> handleError(String message) {
log.error("====---"+message);
return Mono.error(Exception::new);
}
private String generateOrder(ImportedOrderDetails importedOrderDetails)
{
Order requestBody = generateRequestBody(importedOrderDetails);
Mono<OrderResponse> responseForCreatingDemo = orderWebClient()
.post()
.body(Mono.just(requestBody), Order.class)
.retrieve()
.onStatus(
(HttpStatus::is5xxServerError),
(it -> handleError(it.statusCode().getReasonPhrase()))
)
.bodyToMono(OrderResponse.class);
System.out.println("-=-"+responseForCreatingDemo);
if (responseForCreatingOrder != null && responseForCreatingOrder.block().getHeader().getResponseStatus().equals(SUCCESS)){...}
Der Fehler kam von dem .blockTeil in der if-Bedingung. Ich glaube, das ist etwas ziemlich Triviales und es fehlt das große Ganze.
Irgendwelche Vorschläge?
Antworten
Es scheint, dass Sie zwei Arten von Status haben:
- HTTP- Status, definiert durch das Protokoll selbst (siehe HTTP-Antwortstatuscodes )
- Etwas Spezielles für die Anwendung, an der Sie arbeiten, eingekapselt in die
OrderResponseKlasse.
Sie müssen also zwei "Fehler" anstelle von einem behandeln, eine der möglichen Lösungen könnte so aussehen
.retrieve()
.bodyToMono(OrderResponse.class)
// 4xx, 5xx errors and return "Unable to create order" String instead
.onErrorContinue(WebClientResponseException.class, (ex, v) ->
Mono.just("Unable to create order"))
// if application specific status is not "ok" return "Unable to create order"
.map(it -> it.ok ? "Ok response" : "Unable to create order")
.block();
Bitte beachten Sie, dass dieses Codebeispiel die Ausnahme ignoriert und nicht einmal protokolliert