Reputation: 10004
I've two microservices, let us say a FrontEnd and BackEnd, for FrontEnd I'm using WebFlux and calling backend service using feign client as shown in below code excample, though the below code example works, but I wanted to have a generic exception handler using Function and feed onto onErrorMap
@RestController
@Slf4j
public class MyFrentEndService {
@Autowired
private MyBackEndService client;
@PostMapping(value="/hello", consumes="application/json")
public Mono<Void> sayHello(@Valid String msg) {
log.info("Message is {}", msg);
return Mono.create(sink-> {
try {
client.hello(msg);
}catch (FeignException e) {
System.out.println(e.status());
HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
String message = e.getMessage();
sink.error(new ResponseStatusException(status, message));
}
sink.success();
});
}
}
Tried to use onErrorMap
, but getting compilation error stating, use Mono instead of Mono<Void>
@RestController
@Slf4j
public class MyFrentEndService {
@Autowired
private MyBackEndService client;
@PostMapping(value="/hello", consumes="application/json")
public Mono<Void> sayHello(@Valid String msg) {
log.info("Message is {}", msg);
return Mono.fromSupplier(() -> {
client.hello(msg);
return null;
}).onErrorMap(e->{
HttpStatus status = e.status() ==0 } HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
String message = e.getMessage();
return new ResponseStatusException(status, message);
});
}
}
How to use onErrorMap
?
Upvotes: 2
Views: 17859
Reputation: 218
This error is unrelated to the operator onErrorMap
. This code dont compile because the compiler can not infer the generic type returned by the method Mono.fromSupplier
to be Void
- you are returning null on the supplied function.
This should be corrected by doing the following:
@PostMapping(value="/hello", consumes="application/json")
public Mono<Void> sayHello(@Valid String msg) {
log.info("Message is {}", msg);
return Mono.<Void>fromSupplier(() -> {
client.hello(msg);
return null;
}).onErrorMap(e->{
HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
String message = e.getMessage();
return new ResponseStatusException(status, message);
});
}
I think that it is more idiomatic to do the following:
@PostMapping(value="/hello", consumes="application/json")
public Mono<Void> sayHello(@Valid String msg) {
log.info("Message is {}", msg);
return Mono.fromRunnable(() -> {
client.hello(msg);
})
.then()
.onErrorMap(e->{
HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
String message = e.getMessage();
return new ResponseStatusException(status, message);
});
}
Finally, I would advise against using blocking calls inside the reactive pipeline unless you really have to. (prefer WebClient or other nonblocking HTTP client over blocking clients as feign).
Upvotes: 2