Read Error Response Body in Java

Read error response body in Java

Here is the bug report (close, will not fix, not a bug).

Their advice there is to code like this:

HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
_is = httpConn.getInputStream();
} else {
/* error from server */
_is = httpConn.getErrorStream();
}

How can I get the actual error behind HttpResponseException?

Why do you use BasicResponseHandler()? The handler is doing that for you. That handler is just an example and shouldn't be used in real code.

You should either write your own handler or call execute without a handler.

For example,

        HttpResponse response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
responseBody = entity.getContent();

if (statusCode != 200) {
// responseBody will have the error response
}

Retrofit 2.0 how to get deserialised error response.body

solved it by:

Converter<MyError> converter = 
(Converter<MyError>)JacksonConverterFactory.create().get(MyError.class);
MyError myError = converter.fromBody(response.errorBody());

Why is it important to read the response body of an HTTP request?

I believe the intent of this code is indeed to consume the response body so that the connection can be reused. However, I'm not sure that this approach is correct; it is also likely to depend on the version of Java you are using.

First, it should suffice to get the connection's InputStream and close it; behind the scenes, the body still needs to be read, but closing the stream signals to the connection handler that the application wants to skip the body, and the handler can read and discard the content before putting the connection into a cache for re-use.

However, depending on the status, there could be an error stream instead of an input stream. Even in this case, the body needs to be consumed before the connection can be re-used, but many applications (like this one) don't bother reading the body of an error message. Since Java 7, however, if the error body is small enough, it will be consumed and buffered automatically.

Behind the scenes, a connection cache is used to retain open connections. Although the method names suggest a new connection is opened every time, in fact the cache is first checked for an open connection.

How can I get http response body when request is failed in java?

Try the below code :

package com.abc.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String url = "http://localhost:8888/login?token=token";
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
int responseCode = connection.getResponseCode();
InputStream inputStream;
if (200 <= responseCode && responseCode <= 299) {
inputStream = connection.getInputStream();
} else {
inputStream = connection.getErrorStream();
}

BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));

StringBuilder response = new StringBuilder();
String currentLine;

while ((currentLine = in.readLine()) != null)
response.append(currentLine);

System.out.println(response.toString());
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

Resteasy error response body is unreachable

Look into http://download.eclipse.org/microprofile/microprofile-rest-client-1.0/apidocs/org/eclipse/microprofile/rest/client/ext/ResponseExceptionMapper.html

@Provider
public class CustomResponseExceptionMapper implements ResponseExceptionMapper<RuntimeException> {
public CustomResponseExceptionMapper () {
}

public boolean handles(int statusCode, MultivaluedMap<String, Object> headers) {

}

public CusomExceptionMapper toThrowable(Response response) {
try {
String responseString = (String)response.readEntity(String.class);
............
}
}
}

Or

    public class CustomExceptionMapper
implements ResponseExceptionMapper<Throwable> {
}

Register the ResponseExceptionMapper Provider:

@Path("/xyz")
@RegisterProvider(CustomResponseExceptionMapper.class)
@RegisterRestClient
@Timeout

How to get custom error body message in WebClient properly?

The main issue with the example code you have give is the following line of code

throw new ResourceNotFound(clientHttpResponse.getBody().toString());

The type of this is Flux<DataBuffer>, not the actual response body. This is leading to the issue you are seeing.

The way to solve this is invoking the bodyToMono method on the error response body and mapping to a java object. This can be done via the onStatus operator expose from the web client that allows you to take specific actions on specific status codes.

The code snippet below should resolve this

    webClient.post()
.uri(uriTest).body(Mono.just(req), PartnerShipmentDto.class)
.retrieve()
.onStatus(HttpStatus::isError, res -> res.bodyToMono(ErrorBody.class)
.onErrorResume(e -> Mono.error(new ResourceNotFound("aaaa")))
.flatMap(errorBody -> Mono.error(new ResourceNotFound(errorBody.getMessage())))
)
.bodyToMono(PartnerShipmentDto.class)
.block();

The class ErrorBody should contain all of the fields you want to map from json to the java object. The example below only maps the "message" field.

public class ErrorBody {
private String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}


Related Topics



Leave a reply



Submit