In my request handler, if the passed-in accountId cannot be converted to a valid ObjectId I want to catch the error and send back a meaningful message; however, doing so causes the return type to be incompatible, and I cannot figure out how to achieve this pretty trivial use case.
My code:
@GetMapping("/{accountId}") public Mono<ResponseEntity<Account>> get(@PathVariable String accountId) { log.debug(GETTING_DATA_FOR_ACCOUNT, accountId); try { ObjectId id = new ObjectId(accountId); return repository.findById(id) .map(ResponseEntity::ok) .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); } catch (IllegalArgumentException ex) { log.error(MALFORMED_OBJECT_ID, accountId); // TODO(marco): find a way to return the custom error message. This seems to be currently // impossible with the Reactive API, as using body(message) changes the return type to // be incompatible (and Mono<ResponseEntity<?>> does not seem to cut it). return Mono.just(ResponseEntity.badRequest().build()); } } The body(T body) method changes the type of the returned Mono so that it is (assuming one just sends a String) a Mono<ResponseEntity<String>>; however, changing the method's return type to Mono<ResponseEntity<?>> does not work either:
... return Mono.just(ResponseEntity.badRequest().body( MALFORMED_OBJECT_ID.replace("{}", accountId))); as it gives an "incompatible type" error on the other return statement:
error: incompatible types: Mono<ResponseEntity<Account>> cannot be converted to Mono<ResponseEntity<?>> .switchIfEmpty(Mono.just(ResponseEntity.notFound().build())); Obviously, changing the return type of the method to Mono<?> would work, but the response then is the serialized JSON of the ResponseEntity which is NOT what I want.
I have also tried using the onErrorXxxx() methods, but they do not work here either, as the conversion error happens even before the Flux is computed, and I just get a "vanilla" 400 error with an empty message.
The only way I can think of working around this would be to add a message field to my Account object and return that one, but it's genuinely a horrible hack.
try/catch, if you wish to return an error to the client should return aMono.errorcontaining aResponseStatusException. I suggest reading the getting started guide in the reactor documentation. projectreactor.io/docs/core/release/reference/#getting-started