Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is HttpStatusCodeException.getResponseBodyAsString() empty when called after restTemplate.exchange with httpMethod.POST

Tags:

java

spring

I just ran into that issue and can't get why this happens.

client-snippet:

try {
    ResponseEntity<Credentials> response = this.restTemplate.exchange(uri, HttpMethod.POST, httpEntity,
                    Credentials.class);
    this.userCredentials = response.getBody();
    return this.userCredentials;
} catch (HttpStatusCodeException hsce) {
    logger.error("loginUser failed with code " + hsce.getMessage());
    ObjectMapper mapper = new ObjectMapper();
    TransmissionFailureException tfe = new TransmissionFailureException();
    try {
    if (hsce.getStatusCode() == HttpStatus.UNAUTHORIZED) {
        logger.warn(" HIER " + hsce.getMessage());
        throw (CredentialsIncorrectException) mapper.readValue(hsce.getResponseBodyAsString(), CredentialsIncorrectException.class);
...

When I set HttpMethod to GET (of course on server side too) hsce.getResponseBodyAsString() returns the JSON representation of my error as String as it is supposed to and Parsing/Mapping works as expected.

The weird thing the exact same Request executed whith SoapUI carries the Exception in the body as expected on POST and GET.

Do I get something wrong here or is that some kind of bug?

Any help will be appreciated.

Kind regards

Edit: Json Body shown by Soap UI using GET:

{
"cause": null,
"stackTrace":    [
...
],
"localizedMessage": "No user found with given username...",
"message": "No user found with given username...",
"suppressed": []
}

Json Body shown by Soap UI using POST:

{
"cause": null,
"stackTrace":    [
        ...
],
"localizedMessage": "No user found with given username...",
"message": "No user found with given username...",
"suppressed": []
}

StackTrace is too long, sorry...

like image 518
Jan Kressin Avatar asked Oct 20 '15 08:10

Jan Kressin


1 Answers

I get it why it happens. As i can see from the documentation

"Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents, Netty, and OkHttp through the HttpAccessor.setRequestFactory(org.springframework.http.client.ClientHttpRequestFactory) property."

and see their doc and the warning:

Note that the java.net implementation for HTTP requests may raise an exception when accessing the status of a response that represents an error (e.g. 401). If this is an issue, switch to HttpComponentsClientHttpRequestFactory instead.

so java.net impl raise an exception if status code is 401 (unauthorized).

to get the response body as string just change the request factory to your RestTemplate.

    RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

or

    template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

to use apache http components. See links here and here

like image 53
Nikolay Rusev Avatar answered Sep 19 '22 12:09

Nikolay Rusev