Anu
Anu

Reputation: 90

Spring:RestTemplate: Could not extract response: no suitable HttpMessageConverter

I know multiple posts regarding similar issue present on StackOverflow already and I have also gone through some posts and tried to solve my problem but facing others issue. I'll walk through my implementations and explain challenges faced. Please guide me.

Request Header: 'Content-Type: application/json','Accept: "text/html,application/xml;q=0.9,application/xhtml+xml,text/xml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5,application/json;charset=UTF-8"

API call: ResponseEntity<String> responseEntity = restTemplate.exchange(url, method, httpEntity, String.class, paramMap);

Responding API: Content-Type: application/json

  1. Initially I was getting below exception and gone through multiple posts on SO and implemented this solution: Exception: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class java.lang.String] and content type [application/json]
    Implementation done:

RestTemplate restTemplate = new RestTemplate();

MappingJackson2HttpMessageConverter jackson2Converter = new MappingJackson2HttpMessageConverter(); 
jackson2Converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); 
List<HttpMessageConverter<?>> httpMessageConverters = restTemplate.getMessageConverters();
httpMessageConverters.add(jackson2Converter);

restTemplate.setMessageConverters(httpMessageConverters);

After this change, I started getting, below exception:

java.util.ConcurrentModificationException: null at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:730) at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:795) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:617) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:588) at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:507) at

To solve the above problem, I did below changes:

requestHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE); 

RestTemplate restTemplate = getRestTemplate(); 
List<HttpMessageConverter<?>> httpMessageConverters = getHttpMessageConverters(); 
restTemplate.setMessageConverters(httpMessageConverters); 
 
ResponseEntity<String> responseEntity = restTemplate.exchange(url, method, httpEntity, String.class, paramMap); 
 
 
private List<HttpMessageConverter<?>> getHttpMessageConverters() { 
  StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); 
  stringConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); 
  MappingJackson2HttpMessageConverter jackson2Converter = new MappingJackson2HttpMessageConverter(); 
  jackson2Converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); 
  return new ArrayList<>(Arrays.asList(jackson2Converter, stringConverter));
}

After the above changes I started getting below exception:

Could not read document: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@99ef5fc; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@99ef5fc; line: 1, column: 1]","context":"default","exception":"org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@99ef5fc; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: java.io.PushbackInputStream@99ef5fc; line: 1, column: 1]\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:227)\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:212)\n\tat org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)\n\tat org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:884)\n\tat org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:868)\n\tat org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:622)\n\tat org.springframework.web.client.RestTemplate.execute(RestTemplate.java:588)\n\tat org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:507)\n\tat

Please let me know, where I am doing wrong and what is the gap in my understanding and implementation. Thanks in advance!!

Upvotes: 2

Views: 27209

Answers (1)

dew_the_fifth
dew_the_fifth

Reputation: 141

By default, the Spring RestTemplate will configure itself with a series of HttpMessageConverters based on what is available in the classpath.

https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java

Since you don't appear to be using a custom Jackson ObjectMapper in your MappingJackson2HttpMessageConverter, you don't actually need to configure one. In fact, the only thing you're doing for your message converter is invoking the following:

jackson2Converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); 

Which, as I understand it, is used to indicate that this message converter is capable of converting all media types (which is not true).

I suspect that all you really need is this:

RestTemplate restTemplate = getRestTemplate(); 
 
ResponseEntity<String> responseEntity = restTemplate.exchange(url, method, httpEntity, String.class, paramMap); 

However, even then it might not work since you're providing the following accept criteria in your request:

Accept: "text/html,application/xml;q=0.9,application/xhtml+xml,text/xml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5,application/json;charset=UTF-8"

I would try excluding the accept header first, and if that doesn't work I would try setting it to application/json.

Upvotes: 1

Related Questions