With a very simple project, error handling is unclear.
public class WebfluxApplication {
public static void main(String[] args) {
SpringApplication.run(WebfluxApplication.class, args);
}
}
public class EndpointRouter
{
@Bean
public WebClient webClient() {
return WebClient.builder().build();
}
@Bean
public RouterFunction<ServerResponse> goodRoute(Handler handler, ConfigProperties configProperties) {
log.info(configProperties.toString());
return
RouterFunctions.route(RequestPredicates.GET("/api/v1/integration/ok"),
handler::goodEndpoint)
.and(
RouterFunctions.route(RequestPredicates.GET("/api/v1/integration/notfound") {
handler::badEndpoint));
}
public Mono<ServerResponse> goodEndpoint(ServerRequest r) {
return ServerResponse.ok().build();
}
public Mono<ServerResponse> badEndpoint(ServerRequest r) {
var result = service.badEndpoint();
return ServerResponse
.ok()
.body(result, String.class);
}
public class Service
{
private final WebClient webClient;
private final ConfigProperties configProperties;
public Service(WebClient webClient, ConfigProperties configurationProperties) {
this.webClient = webClient;
this.configProperties = configurationProperties;
}
public Mono<String> badEndpoint() {
return webClient
.get()
.uri(configProperties.getNotfound())
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> {
if(clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)){
return Mono.error(new HttpClientErrorException(HttpStatus.NOT_FOUND,
"Entity not found."));
} else {
return Mono.error(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
}
})
.bodyToMono(String.class);
}
From reading the docs, I shouldn't need to set up a Global error handler for the entire project, I should be able to handle the 404, and return a 404 back to the original caller.
This is the output
2020-08-29 16:52:46.301 ERROR 25020 --- [ctor-http-nio-4] a.w.r.e.AbstractErrorWebExceptionHandler : [b339763e-1] 500 Server Error for HTTP GET "/api/v1/integration/notfound"
org.springframework.web.client.HttpClientErrorException: 404 Entity not found.
at com.stevenpg.restperformance.webflux.Service.lambda$badEndpoint$0(Service.java:30) ~[main/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 404 from GET https://httpbin.org/status/404 [DefaultWebClient]
|_ checkpoint ⇢ Handler com.stevenpg.restperformance.webflux.EndpointRouter$$Lambda$445/0x00000008003ae040@7799b58 [DispatcherHandler]
|_ checkpoint ⇢ HTTP GET "/api/v1/integration/notfound" [ExceptionHandlingWebHandler]
I've also tried using onErrorResume on my Mono from the service, but it never works correct and requires a return of Mono rather than Mono.
The documentation and Stack Overflow don't have many/any examples of making a WebClient call inside a RouterFunction and handling different types of responses.
Just adding onErrorResume solves your problem. Otherwise error is handled in AbstractErrorWebExceptionHandler.
return webClient
.get()
.uri(configProperties.getNotfound())
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> {
if(clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)){
return Mono.error(new HttpClientErrorException(HttpStatus.NOT_FOUND,
"Entity not found."));
} else {
return Mono.error(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR));
}
})
.bodyToMono(String.class)
.onErrorResume( e -> Mono.just(e.getMessage()) );
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.