With Java HttpClient, how to handle responses other than 200 (SUCCESS)?

290 views Asked by At

When using rest template we can handle response statuses other than 200 based on the exception thrown by resttemplate. This article describes this in detail.

By default, the RestTemplate will throw one of these exceptions in the case of an HTTP error:

HttpClientErrorException – in the case of HTTP status 4xx
HttpServerErrorException – in the case of HTTP status 5xx
UnknownHttpStatusCodeException – in the case of an unknown HTTP status

Is a similar approach possible when using java HttpClient. I am using JSONBodyHandler approach to automatically serialize the response into a pojo.

// create a client
var client = HttpClient.newHttpClient();

// create a request
var request = HttpRequest.newBuilder(
       URI.create("https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"))
   .header("accept", "application/json")
   .build();

// use the client to send the request
var response = client.send(request, new JsonBodyHandler<>(APOD.class));

APOD apod = response.body().get();

The above works well when the response is 200 but it does not work when there is some server error or client error.

Say for a client error, with an incorrect api key in the request (i.e query param i.e api_key=Incorrect_KEY), curl --location 'https://api.nasa.gov/planetary/apod?api_key=INCORRECT_KEY' the response from server is 403 -

{
    "error": {
        "code": "API_KEY_INVALID",
        "message": "An invalid api_key was supplied. Get one at https://api.nasa.gov:443"
    }
}

The above is definitely different from APOD.class structure and cannot be deserialzed in to this class. I don't see any exception being thrown by HttpClient and as Jackson tries to deserialze it throws UnrecognizedPropertyException: Unrecognized field "error" and every thing fails. The error response message: An invalid api_key was supplied...etc, from server is important for me so i can correct and resent the request.

How to handle above cases of SUCCESS and ERROR responses from server using the same code flow.

(I am NOT looking at BodyHandlers.ofString() approach as I want to continue using the JSONBodyHandler approach.)

3

There are 3 answers

1
queeg On

Check the responses status code - that's what you are indicating anyway. But even if it is different than 200 you can still evaluate the response body.

0
Nash On

Maybe you can try new a parent class for APOD and other response class which contains error field.

4
Michael Gantman On

Basically you need to check the response before reading the response body. Based on the result (success or failure) you will need to handle the response differently. For success de-serialize your JSON response into your POJO, and for the error obviously you will have a different handling.

If you want to see the example you can take a look at the code of a 3d party HttpClient that I wrote. It comes as part of Open source MgntUtuls library written and maintained by me. You can look at the source code on Git here (or download the library, source code and Javadoc from here). By the way library also has a JsonUtils class that simplifies simple cases for serialization/de-serialization of JSON to POJO. you can take a look at Javadoc or download library as maven artifact from here.