No suitable HttpMessageConverter for response type

Using spring, with this code:

List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); for(HttpMessageConverter httpMessageConverter : messageConverters){ System.out.println(httpMessageConverter); } ResponseEntity<ProductList> productList = restTemplate.getForEntity(productDataUrl,ProductList.class); 

I get

 org.springframework.http.converter.ByteArrayHttpMessageConverter@34649ee4 org.springframework.http.converter.StringHttpMessageConverter@39fba59b org.springframework.http.converter.ResourceHttpMessageConverter@383580da org.springframework.http.converter.xml.SourceHttpMessageConverter@409e850a org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@673074aa org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@1e3b79d3 org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@52bb1b26 org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.mycopmany.ProductList] and content type [text/html;charset=UTF-8] 

Excerpt from pojo:

 @XmlRootElement(name="TheProductList") public class ProductList { @XmlElement(required = true, name = "date") private LocalDate importDate; 
+17
java spring xml jaxb
Feb 18 '14 at 12:48
source share
8 answers

From Spring's point of view, none of the HttpMessageConverter instances registered with RestTemplate can convert text/html content to a ProductList object. The proposed interest is HttpMessageConverter#canRead(Class, MediaType) . The implementation for all of the above returns false , including Jaxb2RootElementHttpMessageConverter .

Since no HttpMessageConverter can read your HTTP response, processing fails with an exception.

If you can control the response of the server, modify it to set the Content-type to application/xml , text/xml or something suitable application/*+xml .

If you do not control the server response, you need to write and register your own HttpMessageConverter (which can extend the Spring classes, see AbstractXmlHttpMessageConverter and its subclasses), which can read and convert text/html .

+20
Feb 18 '14 at 15:02
source

If you cannot change the server type response, you can extend the GsonHttpMessageConverter to handle additional support types

 public class MyGsonHttpMessageConverter extends GsonHttpMessageConverter { public MyGsonHttpMessageConverter() { List<MediaType> types = Arrays.asList( new MediaType("text", "html", DEFAULT_CHARSET), new MediaType("application", "json", DEFAULT_CHARSET), new MediaType("application", "*+json", DEFAULT_CHARSET) ); super.setSupportedMediaTypes(types); } } 
+6
Jan 20 '15 at 8:57
source

You can create a RestTemplateXML class that extends RestTemplate. Then override doExecute(URI, HttpMethod, RequestCallback, ResponseExtractor<T>) and explicitly get response-headers and set the content-type to application/xml .

Now Spring reads the headers and knows that it is `application / xml '. This is a kind of hack, but it works.

 public class RestTemplateXML extends RestTemplate { @Override protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException { logger.info( RestTemplateXML.class.getSuperclass().getSimpleName() + ".doExecute() is overridden"); Assert.notNull(url, "'url' must not be null"); Assert.notNull(method, "'method' must not be null"); ClientHttpResponse response = null; try { ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } response = request.execute(); // Set ContentType to XML response.getHeaders().setContentType(MediaType.APPLICATION_XML); if (!getErrorHandler().hasError(response)) { logResponseStatus(method, url, response); } else { handleResponseError(method, url, response); } if (responseExtractor != null) { return responseExtractor.extractData(response); } else { return null; } } catch (IOException ex) { throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + url + "\":" + ex.getMessage(), ex); } finally { if (response != null) { response.close(); } } } private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse response) { if (logger.isDebugEnabled()) { try { logger.debug(method.name() + " request for \"" + url + "\" resulted in " + response.getRawStatusCode() + " (" + response.getStatusText() + ")"); } catch (IOException e) { // ignore } } } private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException { if (logger.isWarnEnabled()) { try { logger.warn(method.name() + " request for \"" + url + "\" resulted in " + response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler"); } catch (IOException e) { // ignore } } getErrorHandler().handleError(response); } } 
+2
Mar 12 '15 at 15:16
source

Try the following:

 <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.6.0</version> </dependency> 
+1
Jul 29 '16 at 17:10
source

If you use Spring Boot, you can make sure that you have Jackson dependent on your class path. You can do it manually with:

  <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> 

Or you can use a web starter:

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 
+1
Aug 30 '16 at 11:19
source

Or you can use

public void setSupportedMediaTypes (list supported by MediaTypes)

which belongs to AbstractHttpMessageConverter<T> to add some ContentTypes that you like. This method can give the answer MappingJackson2HttpMessageConverter canRead() and convert it to the desired class, which in this case is the ProductList class.

and I think this step should connect to Spring context initialization. for example using

implements ApplicationListener {...}

0
Dec 25 '15 at 5:47
source

In addition to all the answers, if you got the answer in the text/html response while you were expecting something else (i.e. application/json ), it might suggest that an error occurred on the server side (say 404 ) and the error page was returned instead of your data.

It happened in my case. Hope this saves you some time.

0
05 Oct '17 at 12:35 on
source

This does not answer the problem, but if someone comes to this question when they stumbled upon this exception without finding a suitable message converter, here is my problem and solution.

In Spring 4.0.9 we were able to send this

  JSONObject jsonCredential = new JSONObject(); jsonCredential.put(APPLICATION_CREDENTIALS, data); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity<String> res = restTemplate.exchange(myRestUrl), HttpMethod.POST,request, String.class); 

In the release of Spring 4.3.5, we begin to see errors with the message that the converter was not found. The way CONverets works is that if you use it in your classpath, they are registered. Jackson-asl is still on the class path, but spring is not recognized. We are replacing Jackson-asl with a faster jackson core. As soon as we added, I could see that the registered converter enter image description here

-one
Jul 12 '17 at 15:46 on
source



All Articles