web-dev-qa-db-ger.com

es wurde kein geeigneter HttpMessageConverter für den Antworttyp gefunden

Verwenden Sie den Frühling mit diesem Code:

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

Ich bekomme 

o[email protected]34649ee4
[email protected]fba59b
[email protected]383580da
or[email protected]409e850a
org.springframework[email protected]673074aa
org.springfr[email protected]1e3b79d3
org.springfr[email protected]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]

Ein Ausschnitt des Pojo:

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

@XmlElement(required = true, name = "date")
private LocalDate importDate;
29
NimChimpsky

Aus der Frühlingssicht kann keine der mit HttpMessageConverter registrierten RestTemplate-Instanzen text/html-Inhalt in ein ProductList-Objekt konvertieren. Die Methode von Interesse ist HttpMessageConverter#canRead(Class, MediaType). Die Implementierung für alle oben genannten Ergebnisse gibt false zurück, einschließlich Jaxb2RootElementHttpMessageConverter

Da keine HttpMessageConverter Ihre HTTP-Antwort lesen kann, schlägt die Verarbeitung mit einer Ausnahme fehl.

Wenn Sie die Serverantwort steuern können, ändern Sie sie, um den Content-type auf application/xml, text/xml oder etwas anderes festzulegen, das application/*+xml entspricht.

Wenn Sie die Serverantwort nicht steuern, müssen Sie Ihre eigene HttpMessageConverter schreiben und registrieren (die Spring-Klassen erweitern kann, siehe AbstractXmlHttpMessageConverter und ihre Unterklassen), die text/html lesen und konvertieren kann.

26

Wenn Sie die Antwort des Servermedientyps nicht ändern können, können Sie GsonHttpMessageConverter um die Verarbeitung zusätzlicher Supporttypen erweitern

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);
    }
}
8
Vadim Zin4uk

Wenn Sie Spring Boot verwenden, möchten Sie möglicherweise sicherstellen, dass Sie die Jackson-Abhängigkeit in Ihrem Klassenpfad haben. Sie können dies manuell tun über:

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

Oder Sie können den Webstarter verwenden:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
6
Wim Deblauwe

Sie können die Klasse RestTemplateXML erstellen, die RestTemplate erweitert. Dann überschreiben Sie doExecute(URI, HttpMethod, RequestCallback, ResponseExtractor<T>) und erhalten Sie explizit response-headers und setzen Sie content-type auf application/xml

Nun liest Spring die Header und weiß, dass es sich um "application/xml" handelt. Es ist eine Art Hack, aber es funktioniert.

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);
  }
}
3
Chester Leung

Sie können Ihrem RestTemplate auch einfach anweisen, alle Medientypen zu akzeptieren:

@Bean
public RestTemplate restTemplate() {
   return new RestTemplate();
   final RestTemplate restTemplate = new RestTemplate();

   List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
   MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
   converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
   messageConverters.add(converter);
   restTemplate.setMessageConverters(messageConverters);

   return restTemplate;
}
2
Markoorn

Wenn Sie zusätzlich zu allen Antworten in Antwort text/html empfangen werden, während Sie etwas anderes erwartet haben (z. B. application/json), kann dies auf einen Fehler auf der Serverseite (z. B. 404) hinweisen und die Fehlerseite wurde statt zurückgegeben deine Daten.

So ist es in meinem Fall passiert. Ich hoffe, es wird jemandem Zeit sparen.

1
user1913596

Oder du kannst verwenden 

public void setSupportedMediaTypes (Liste unterstützterMediaTypes) 

methode, die zu AbstractHttpMessageConverter<T> gehört, um eine ContentTypes hinzuzufügen, die Ihnen gefällt. Auf diese Weise kann die MappingJackson2HttpMessageConvertercanRead() Ihre Antwort erhalten und diese in Ihre gewünschte Klasse umwandeln, die in diesem Fall ProductList-Klasse ist.

ich denke, dieser Schritt sollte mit der Initialisierung des Spring Context verbunden sein. zum Beispiel mit 

implementiert ApplicationListener { ... }

0
avidya

Versuche dies:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.0</version>
</dependency>
0
Leonardozm

Eine Verfeinerung von Vadim Zin4uks Antwort dient nur der Verwendung der vorhandenen GsonHttpMessageConverter-Klasse, ruft jedoch den setSupportedMediaTypes () - Setter auf.

Für Spring Boot-Apps führt dies dazu, dass folgende Konfigurationsklassen hinzugefügt werden:

@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