no suitable HttpMessageConverter found for response type

前端 未结 10 1766
深忆病人
深忆病人 2020-11-30 02:33

Using spring, with this code :

List> messageConverters = restTemplate.getMessageConverters();
for(HttpMessageConverter ht         


        
相关标签:
10条回答
  • 2020-11-30 02:40

    A refinement of Vadim Zin4uk's answer is just to use the existing GsonHttpMessageConverter class but invoke the setSupportedMediaTypes() setter.

    For spring boot apps, this results into adding to following to your configuration classes:

    @Bean
    public GsonHttpMessageConverter gsonHttpMessageConverter(Gson gson) {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        converter.setGson(gson);
        List<MediaType> supportedMediaTypes = converter.getSupportedMediaTypes();
        if (! supportedMediaTypes.contains(TEXT_PLAIN)) {
            supportedMediaTypes = new ArrayList<>(supportedMediaTypes);
            supportedMediaTypes.add(TEXT_PLAIN);
            converter.setSupportedMediaTypes(supportedMediaTypes);
        }
        return converter;
    }
    
    0 讨论(0)
  • 2020-11-30 02:42

    From a Spring point of view, none of the HttpMessageConverter instances registered with the RestTemplate can convert text/html content to a ProductList object. The method of 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 server response, modify it to set the Content-type to application/xml, text/xml, or something matching application/*+xml.

    If you don't control the server response, you'll need to write and register your own HttpMessageConverter (which can extend the Spring classes, see AbstractXmlHttpMessageConverter and its sub classes) that can read and convert text/html.

    0 讨论(0)
  • 2020-11-30 02:46

    This is not answering the problem but if anyone comes to this question when they stumble upon this exception of no suitable message converter found, 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 Spring 4.3.5 release, we starting seeing errors with the message that converter was not found. The way COnverets work is that if you have it in your classpath, they get registered.jackson-asl was still in classpath but was not being recognized by spring. We replace Jackson-asl with faster-xml jackson core. Once we added I could see the converter being registered

    0 讨论(0)
  • 2020-11-30 02:54

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

    Now Spring reads the headers and knows that it is `application/xml'. It is kind of a 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);
      }
    }
    
    0 讨论(0)
  • 2020-11-30 02:54

    Or you can use

    public void setSupportedMediaTypes(List supportedMediaTypes)

    method which belongs to AbstractHttpMessageConverter<T>, to add some ContentTypes you like. This way can let the MappingJackson2HttpMessageConverter canRead() your response, and transform it to your desired Class, which on this case,is ProductList Class.

    and I think this step should hooked up with the Spring Context initializing. for example, by using

    implements ApplicationListener { ... }

    0 讨论(0)
  • 2020-11-30 02:56

    In addition to all the answers, if you happen to receive in response text/html while you've expected something else (i.e. application/json), it may suggest that an error occurred on the server side (say 404) and the error page was returned instead of your data.

    So it happened in my case. Hope it will save somebody's time.

    0 讨论(0)
提交回复
热议问题