springresttemplate

Spring RestTemplate - HttpClientErrorException.getResponseBodyAsString() returns unparseable value


I am using Spring RestTemplate and having issue while catching an HttpClientErrorException with postForEntity(). The Exception's getResponseBodyAsString() method gets some random characters in the String value.

try{
    HttpEntity<Object> reqEntity = new HttpEntity<Object>(objPayload, headers);
    ResponseEntity<Object> resEntity = restTemplate.postForEntity(url, reqEntity, Object.class);
} catch(HttpStatusCodeException he) {
    log.error("Exception Status: {} -  {}", he.getStatusCode(), he.getStatusText());
    log.error("Exception - header {} ", he.getResponseHeaders());
    log.error("\n Exception - message  {} ", he.getResponseBodyAsString());
}

Exception message:

2024-02-01 14:48:28.801 ERROR [http-nio-8888-exec-2][APIController:318] Exception Status: 400 BAD_REQUEST -  Bad Request
<br/>
2024-02-01 14:48:28.802 ERROR [http-nio-8888-exec-2][APIController:319] Exception - header : [X-API-Mode:"Sandbox", Content-Encoding:"gzip", Content-Type:"application/json", Content-Length:"192", Server:"server-Gateway", Date:"Thu, 01 Feb 2024 19:48:28 GMT", Connection:"close", Server-Timing:"cdn-cache; desc=MISS", "edge; dur=25", "origin; dur=753", "ak_p; desc="1706816908113_1611090436_118439255_77820_5277_40_0_-";dur=1"]

The returned String with the strange characters:

2024-02-01 14:48:28.802 ERROR [http-nio-8888-exec-2][APIController:320] 
Exception - message    �       ��
        �@F_�2��ҝd� �hQ���\k�f`�&��������F�m@��Y�E!��-a�m�4Y��<�]��jݩ��3���A�Q(�i
        ˪:�6��Rֱ<^�ZV����1+�'���w-#Ӳ�n0V��p�Ͳq����wg,�ǀ���u   ��I�  `À/�c����$u^� 

Making a request to the same endpoint using Postman I can't reproduce the issue:

{
    "transactionId": "063dfe4c-07c3-4dc1-b495-e0ae41520",
    "errors": [
        {
            "code": "INVALID.INPUT.EXCEPTION",
            "message": "Invalid field value"
        }
    ]
}

Solution

  • The Content-Encoding in the log says gzip which means the API you are calling is returning a response compressed in gzip format, which Postman can decompress and display as JSON. However the default RestTemplate lacks the ability to decompress JSON, hence the strange characters in the log. You can customize the RestTemplate bean to internally use Apache HttpClient, which can handle gzip compressed responses.

    Bean definition:

    import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class AppConfig {
    
        @Bean
        public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
                    HttpClientBuilder.create().build()
            );
            RestTemplate restTemplate = restTemplateBuilder.build();
            restTemplate.setRequestFactory(requestFactory);
    
            return restTemplate;
        }
    }
    

    Additional dependency:

    implementation group: 'org.apache.httpcomponents.client5', name: 'httpclient5', version: '5.3.1'