aucun convertisseur de type HttpMessageConverter adapté n'a été trouvé pour le type de réponse

à l'Aide de printemps, avec ce code :

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

je

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]

un extrait de la pojo :

@XmlRootElement(name="TheProductList")
public class ProductList {

@XmlElement(required = true, name = "date")
private LocalDate importDate;
26
demandé sur Koray Tugay 2014-02-18 16:48:44

9 réponses

du point de vue du printemps, aucun des HttpMessageConverter instances enregistrées avec le RestTemplate peut convertir text/html contenu ProductList objet. La méthode d'intérêt est HttpMessageConverter#canRead(Class, MediaType). La mise en œuvre de tous les ci-dessus renvoie falseJaxb2RootElementHttpMessageConverter.

Depuis pas HttpMessageConverter peut lire votre réponse HTTP, le traitement échoue avec une exception.

si vous pouvez contrôler la réponse du serveur, Modifiez - la pour définir le Content-typeapplication/xml,text/xml, ou quelque chose correspondant à application/*+xml.

si vous ne contrôlez pas la réponse du serveur, vous devrez écrire et enregistrer votre propre HttpMessageConverter (qui peut étendre les classes de ressorts, voir AbstractXmlHttpMessageConverter et ses sous-classes) qui peut lire et convertir text/html.

24
répondu Sotirios Delimanolis 2014-02-18 15:02:32

si vous ne pouvez pas modifier la réponse de type média du serveur, vous pouvez étendre GsonHttpMessageConverter pour traiter des types de support supplémentaires

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);
    }
}
7
répondu Vadim Zin4uk 2015-01-20 08:57:48

si vous utilisez Spring Boot, vous pourriez vouloir vous assurer que vous avez la dépendance Jackson dans votre chemin de classe. Vous pouvez le faire manuellement via:

    <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>

Ou vous pouvez utiliser le web starter:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
5
répondu Wim Deblauwe 2016-08-30 11:19:18

vous pouvez créer une classe, RestTemplateXML, qui étend RestTemplate. Alors outrepassez doExecute(URI, HttpMethod, RequestCallback, ResponseExtractor<T>), et explicitement get response-headers et définissez content-typeapplication/xml.

maintenant Spring lit les en-têtes et sait qu'il est `application/xml'. C'est un peu un piratage, mais ça marche.

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
répondu Chester Leung 2015-03-12 15:16:48

essaye ceci:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.0</version>
</dependency>
1
répondu Leonardozm 2016-07-29 17:42:22

en plus de toutes les réponses, si vous recevez une réponse text/html alors que vous vous attendiez à autre chose (i.e. application/json), cela peut suggérer qu'une erreur s'est produite du côté du serveur (disons 404) et que la page d'erreur a été retournée au lieu de vos données.

Donc ça c'est passé dans mon cas. Espérons qu'il permettra de sauver quelqu'un.

1
répondu user1913596 2017-10-05 12:35:55

Ou vous pouvez utiliser

public void setSupportedMediaTypes (Listsupportedmediatypes)

méthode qui appartient à AbstractHttpMessageConverter<T> ajouter ContentTypes vous le souhaitez. De cette façon, peut laisser l' MappingJackson2HttpMessageConverter canRead() votre réponse, et la transformer à votre classe désirée,qui sur ce cas, est la classe ProductList.

et je pense que cette étape devrait être raccordée avec le contexte Spring initialisant. par exemple, en utilisant

met en œuvre ApplicationListener { ... }

0
répondu avidya 2015-12-25 05:47:20

Un raffinement de réponse de Vadim Zin4uk est juste pour utiliser la classe GsonHttpMessageConverter existante mais invoquer le setsupportedmediatypes () setter.

pour les applications de démarrage de printemps, cela se traduit par un ajout à la liste suivante de vos classes de configuration:

@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
répondu Guillaume Berche 2018-02-22 15:34:42

ce n'est pas répondre au problème mais si quelqu'un vient à cette question quand ils trébuchent sur cette exception d'aucun convertisseur de message approprié trouvé, voici mon problème et la solution.

Au Printemps 4.0.9, nous avons été en mesure d'envoyer ce

    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);

au printemps 4.3.5 libération, nous commençons à voir des erreurs avec le message que le convertisseur n'a pas été trouvé. La façon dont COnverets fonctionne est que si vous l'avez dans votre chemin de classe, ils sont enregistrés.jackson-asl était encore en classe. mais n'a pas été reconnu par le printemps. Nous remplaçons Jackson-asl par plus rapide-XML jackson core. Une fois que nous avons ajouté, je pouvais voir le convertisseur enregistré enter image description here

-1
répondu vsingh 2017-07-12 15:46:24