[json] RestClientException: Could not extract response. no suitable HttpMessageConverter found

Using the curl command:

curl -u 591bf65f50057469f10b5fd9:0cf17f9b03d056ds0e11e48497e506a2 https://backend.tdk.com/api/devicetypes/59147fd79e93s12e61499ffe/messages

I am getting a JSON response:

{"data":[{"device":"18SE62","time":1494516023,"data":"3235","snr":"36.72",...

I save the response on a txt file and parse it using jackson, and everything is fine

ObjectMapper mapper = new ObjectMapper();
        File f = new File(getClass().getResource
                    ("/result.json").getFile());
        MessageList messageList = mapper.readValue(f, MessageList.class);

and I assume I should get the same result using RestTemplate but that's not the case

RestTemplate restTemplate = new RestTemplate();
        MessageList messageList = 
                restTemplate.getForObject("http://592693f43c87815f9b8145e9:[email protected]/api/devicetypes/591570373c87894b4eece34d/messages", MessageList.class);

I got an error instead

Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)
    at com.tdk.controllers.restful.client.RestTemplateExample.main(RestTemplateExample.java:27)

I tried to set the contentType:

HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);


        MessageList messageList = 
                restTemplate.getForObject(url, entity, MessageList.class);

but then I got a compilation error

The method getForObject(String, Class<T>, Object...) in the type RestTemplate is not applicable for the arguments (String, HttpEntity<String>, 
 Class<MessageList>)

I also tried to add a the Jackson Message converter

  List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();        
            //Add the Jackson Message converter
            messageConverters.add(new MappingJackson2HttpMessageConverter());    
            //Add the message converters to the restTemplate
            restTemplate.setMessageConverters(messageConverters); 

            MessageList messageList = 
                    restTemplate.getForObject(url, MessageList.class);

But then I got this error:

Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)
    at com.tdk.controllers.restful.client.RestTemplateExample.main(RestTemplateExample.java:51)

I also tried adding the class

@Configuration
@EnableWebMvc
public class MvcConf extends WebMvcConfigurationSupport {

    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(converter());
        addDefaultHttpMessageConverters(converters);
    }

    @Bean
    MappingJackson2HttpMessageConverter converter() {

        MappingJackson2HttpMessageConverter converter 
                    = new MappingJackson2HttpMessageConverter();
        return converter;
    }

}

but I got the error:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)

This question is related to json spring rest spring-mvc resttemplate

The answer is


While the accepted answer solved the OP's original problem, most people finding this question through a Google search are likely having an entirely different problem which just happens to throw the same no suitable HttpMessageConverter found exception.

What happens under the covers is that MappingJackson2HttpMessageConverter swallows any exceptions that occur in its canRead() method, which is supposed to auto-detect whether the payload is suitable for json decoding. The exception is replaced by a simple boolean return that basically communicates sorry, I don't know how to decode this message to the higher level APIs (RestClient). Only after all other converters' canRead() methods return false, the no suitable HttpMessageConverter found exception is thrown by the higher-level API, totally obscuring the true problem.

For people who have not found the root cause (like you and me, but not the OP), the way to troubleshoot this problem is to place a debugger breakpoint on onMappingJackson2HttpMessageConverter.canRead(), then enable a general breakpoint on any exception, and hit Continue. The next exception is the true root cause.

My specific error happened to be that one of the beans referenced an interface that was missing the proper deserialization annotations.

UPDATE FROM THE FUTURE

This has proven to be such a recurring issue across so many of my projects, that I've developed a more proactive solution. Whenever I have a need to process JSON exclusively (no XML or other formats), I now replace my RestTemplate bean with an instance of the following:

public class JsonRestTemplate extends RestTemplate {

    public JsonRestTemplate(
            ClientHttpRequestFactory clientHttpRequestFactory) {
        super(clientHttpRequestFactory);

        // Force a sensible JSON mapper.
        // Customize as needed for your project's definition of "sensible":
        ObjectMapper objectMapper = new ObjectMapper()
                .registerModule(new Jdk8Module())
                .registerModule(new JavaTimeModule())
                .configure(
                        SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter() {

            public boolean canRead(java.lang.Class<?> clazz,
                    org.springframework.http.MediaType mediaType) {
                return true;
            }    
            public boolean canRead(java.lang.reflect.Type type,
                    java.lang.Class<?> contextClass,
                    org.springframework.http.MediaType mediaType) {
                return true;
            }
            protected boolean canRead(
                    org.springframework.http.MediaType mediaType) {
                return true;
            }
        };

        jsonMessageConverter.setObjectMapper(objectMapper);
        messageConverters.add(jsonMessageConverter);
        super.setMessageConverters(messageConverters);

    }
}

This customization makes the RestClient incapable of understanding anything other than JSON. The upside is that any error messages that may occur will be much more explicit about what's wrong.


Please add the shared dependency having jackson databind package . Hope this will clear the issue.

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

Here is the approach I follow whenever I see this type of error:

  1. One way to debug this issue is by first taking whatever response is coming as String.class then applying Gson().fromJson(StringResp.body(), MyDTO.class). It will still fail most probably but this time it will throw the fields which are creating this error to happen in first place. Post the modification, we can use the previous approach as usual.

ResponseEntity<String> respStr = restTemplate.exchange(URL,HttpMethod.GET, entity, String.class);
Gson g = new Gson();

The below step will throw error with the fields which is causing the issue

MyDTO resp = g.fromJson(respStr.getBody(), MyDTO.class);

I don't have the error message with me but it will point to the field which is problematic and the reason for it. Resolve those and try again with previous approach.


In my case @Ilya Dyoshin's solution didn't work: The mediatype "*" was not allowed. I fix this error by adding a new converter to the restTemplate this way during initialization of the MockRestServiceServer:

  MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = 
                      new MappingJackson2HttpMessageConverter();
  mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
                                    Arrays.asList(
                                       MediaType.APPLICATION_JSON, 
                                       MediaType.APPLICATION_OCTET_STREAM));
  restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
  mockServer = MockRestServiceServer.createServer(restTemplate);

(Based on the solution proposed by Yashwant Chavan on the blog named technicalkeeda)

JN Gerbaux


I was trying to use Feign, while I encounter same issue, As I understood HTTP message converter will help but wanted to understand how to achieve this.

@FeignClient(name = "mobilesearch", url = "${mobile.search.uri}" ,
        fallbackFactory = MobileSearchFallbackFactory.class,
        configuration = MobileSearchFeignConfig.class)
public interface MobileSearchClient {

    @RequestMapping(method = RequestMethod.GET)
    List<MobileSearchResponse> getPhones();
}

You have to use Customer Configuration for the decoder, MobileSearchFeignConfig,

public class MobileSearchFeignConfig {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }


    @Bean
    public Decoder feignDecoder() {
        return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
    }

    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new MappingJackson2HttpMessageConverter());
        return new ObjectFactory<HttpMessageConverters>() {
            @Override
            public HttpMessageConverters getObject() throws BeansException {
                return httpMessageConverters;
            }
        };
    }

    public class MappingJackson2HttpMessageConverter extends org.springframework.http.converter.json.MappingJackson2HttpMessageConverter {
        MappingJackson2HttpMessageConverter() {
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
            setSupportedMediaTypes(mediaTypes);
        }
    }

}

Spring sets the default content-type to octet-stream when the response is missing that field. All you need to do is to add a message converter to fix this.


If the above response by @Ilya Dyoshin didn't still retrieve, try to get the response into a String Object.

(For my self thought the error got solved by the code snippet by Ilya, the response retrieved was a failure(error) from the server.)

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
ResponseEntity<String> st = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class); 

And Cast to the ResponseObject DTO (Json)

Gson g = new Gson();
DTO dto = g.fromJson(st.getBody(), DTO.class); 

I was having a very similar problem, and it turned out to be quite simple; my client wasn't including a Jackson dependency, even though the code all compiled correctly, the auto-magic converters for JSON weren't being included. See this RestTemplate-related solution.

In short, I added a Jackson dependency to my pom.xml and it just worked:

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

In my case it was caused by the absence of the jackson-core, jackson-annotations and jackson-databind jars from the runtime classpath. It did not complain with the usual ClassNothFoundException as one would expect but rather with the error mentioned in the original question.


You need to create your own converter and implement it before making a GET request.

RestTemplate  restTemplate = new RestTemplate();

List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();        

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));         
messageConverters.add(converter);  
restTemplate.setMessageConverters(messageConverters);    

Other possible solution : I tried to map the result of a restTemplate.getForObject with a private class instance (defined inside of my working class). It did not work, but if I define the object to public, inside its own file, it worked correctly.


Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?

Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to rest

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Returning data from Axios API Access Control Origin Header error using Axios in React Web throwing error in Chrome JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value How to send json data in POST request using C# How to enable CORS in ASP.net Core WebAPI RestClientException: Could not extract response. no suitable HttpMessageConverter found REST API - Use the "Accept: application/json" HTTP Header 'Field required a bean of type that could not be found.' error spring restful API using mongodb MultipartException: Current request is not a multipart request

Examples related to spring-mvc

Two Page Login with Spring Security 3.2.x ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Spring 5.0.3 RequestRejectedException: The request was rejected because the URL was not normalized The type WebMvcConfigurerAdapter is deprecated RestClientException: Could not extract response. no suitable HttpMessageConverter found Spring boot: Unable to start embedded Tomcat servlet container UnsatisfiedDependencyException: Error creating bean with name 8080 port already taken issue when trying to redeploy project from Spring Tool Suite IDE Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed Difference between the annotations @GetMapping and @RequestMapping(method = RequestMethod.GET)

Examples related to resttemplate

RestClientException: Could not extract response. no suitable HttpMessageConverter found How to POST form data with Spring RestTemplate? Spring Resttemplate exception handling Could not autowire field:RestTemplate in Spring boot application RestTemplate: How to send URL and query parameters together How to autowire RestTemplate using annotations Multipart File Upload Using Spring Rest Template + Spring Web MVC Could not read JSON: Can not deserialize instance of hello.Country[] out of START_OBJECT token Get list of JSON objects with Spring RestTemplate How to disable SSL certificate checking with Spring RestTemplate?