Search code examples
micronaut

Using Declarative Client Exceptions always throws 500 from Controller


I've got a declarative client interface and I am using it from a controller. I fully expect authentication with my service to fail right now, but I'm curious why I can't manage that exception...

@Controller("/order-gateway/orders")
public class OrderController {
    private final OrderClient client;

    public OrderController(OrderClient client) {
        this.client = client;
    }

    @Post
    @Produces(MediaType.TEXT_PLAIN)
    public Single<String> createOrder() {
        return client.createOrder();
    }
}

All of the above is just sample code but when the client calls the service endpoint, it isn't authorized and returns a 401. But my controller above is returning a 500 because client.createOrder() is throwing an exception from getting the 401.

I kind of expected to be able to handle that but I have tried doOnErrors and other methods that don't seem to prevent the 500. If anything, I'd want to bubble up the 401 or at the very least, handle the 500 more gracefully. But I don't even know how to get the status code of the service call out of the async response.


Solution

  • So something like this is likely what you're looking for:

        @Post
        @Produces(MediaType.TEXT_PLAIN)
        Single<MutableHttpResponse<String>> createOrder() {
            return client.createOrder()
                    .map(HttpResponse::ok)
                    .onErrorReturn(t -> {
                        HttpClientResponseException exception = (HttpClientResponseException) t;
                        return HttpResponse.status(exception.getStatus());
                    });
        }
    

    In order to propagate the response status you have to return an http response instead of just the body publisher. That then requires you to map the client call to a response in the success case. In the example above I also am using onErrorReturn to return a response in the case of an error.