it-swarm.com.de

RestClientException: Antwort konnte nicht extrahiert werden. kein passender HttpMessageConverter gefunden

Verwenden des Befehls curl:

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

Ich erhalte eine JSON-Antwort:

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

Ich speichere die Antwort in einer txt-Datei und analysiere sie mit Jackson, und alles ist in Ordnung

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

und ich gehe davon aus, dass ich mit RestTemplate das gleiche Ergebnis erzielen sollte, aber das ist nicht der Fall

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

Ich habe stattdessen einen Fehler erhalten

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)

Ich habe versucht, den contentType zu setzen:

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

aber dann habe ich einen Kompilierungsfehler bekommen

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

Ich habe auch versucht, einen Jackson Message-Konverter hinzuzufügen

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

Aber dann habe ich diesen Fehler bekommen:

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)

Ich habe auch versucht, die Klasse hinzuzufügen

@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;
    }

}

aber ich habe den Fehler bekommen:

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

Das Hauptproblem hierbei ist Inhaltstyp [text/html; charset = iso-8859-1] vom Dienst empfangen, der tatsächliche Inhaltstyp sollte jedoch application/json; charset = iso) sein -8859-1

Um dies zu überwinden, können Sie einen benutzerdefinierten Nachrichtenkonverter einführen. und registriere es für alle Arten von Antworten (d. h. ignoriere den Antwortinhaltstyp-Header). Genau wie dieser

List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();        
//Add the Jackson Message converter
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

// Note: here we are making this converter to process any kind of response, 
// not only application/*json, which is the default behaviour
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));        
messageConverters.add(converter);  
restTemplate.setMessageConverters(messageConverters); 
72
Ilya Dyoshin

Ich hatte ein sehr ähnliches Problem, und es stellte sich als recht einfach heraus. Mein Client enthielt keine Jackson-Abhängigkeit, obwohl der Code vollständig kompiliert war und die Auto-Magic-Konverter für JSON nicht enthalten waren. Siehe diese RestTemplate-bezogene Lösung

Kurz gesagt, ich habe meiner pom.xml eine Jackson-Abhängigkeit hinzugefügt und es hat einfach funktioniert:

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

Während die akzeptierte Antwort das ursprüngliche Problem des OP löste, vermute ich, dass die meisten Leute, die diese Frage über eine Google-Suche finden, wahrscheinlich (statistisch gesehen) ein ganz anderes Problem haben, das zufällig dasselbe verursacht . Keine passende HttpMessageConverter-Ausnahme gefunden .

Was unter der Decke passiert, ist, dass MappingJackson2HttpMessageConverter Alle Ausnahmen verschluckt, die in seiner canRead() -Methode auftreten, die automatisch erkennen soll, ob die Nutzdaten für die JSON-Dekodierung geeignet sind. Die Ausnahme wird durch eine einfache boolesche Rückgabe ersetzt, die im Grunde genommen kommuniziert . Entschuldigung, ich weiß nicht, wie ich diese Nachricht an die übergeordneten APIs (RestClient). Erst nachdem alle canRead () -Methoden anderer Konverter den Wert false zurückgegeben haben, wird die Ausnahme , dass kein passender HttpMessageConverter gefunden wurde , von der API der höheren Ebene ausgelöst, wodurch die Gültigkeit vollständig verdeckt wird Problem.

Für Personen, die die Hauptursache nicht gefunden haben (wie Sie und ich, aber nicht das OP), besteht die Möglichkeit zur Behebung dieses Problems darin, einen Debugger-Haltepunkt auf onMappingJackson2HttpMessageConverter.canRead() zu setzen und dann in jeder Ausnahme einen allgemeinen Haltepunkt zu aktivieren und drücken Sie Weiter. Die nächste Ausnahme ist die wahre Grundursache.

Mein spezifischer Fehler war zufällig, dass eine der Beans auf eine Schnittstelle verwies, der die richtigen Deserialisierungsanmerkungen fehlten.

13
Alex R

Wenn die obige Antwort von @ Ilya Dyoshin immer noch nicht abgerufen wurde, versuchen Sie, die Antwort in ein String-Objekt zu übertragen.

(Meiner Meinung nach wurde der Fehler durch das Code-Snippet von Ilya behoben. Die abgerufene Antwort war ein Fehler vom 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); 

Und an das ResponseObject DTO (Json) übergeben

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

In meinem Fall hat die Lösung von @Ilya Dyoshin nicht funktioniert: Der Medientyp "*" war nicht erlaubt. Ich behebe diesen Fehler, indem ich während der Initialisierung des MockRestServiceServers einen neuen Konverter zur restTemplate hinzufüge:

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

(Basierend auf der von Yashwant Chavan im Blog "technicalkeeda" vorgeschlagenen Lösung)

JN Gerbaux

2
JN Gerbaux

In meinem Fall wurde dies durch das Fehlen des Jackson-Core, der Jackson-Annotations und der Jackson-Databind-Jars aus dem Laufzeitklassenpfad verursacht. Es hat sich nicht wie erwartet mit der üblichen ClassNothFoundException beschwert, sondern mit dem in der ursprünglichen Frage genannten Fehler.

1
ikolomiyets

Sie müssen Ihren eigenen Konverter erstellen und implementieren, bevor Sie eine GET-Anfrage stellen.

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);    
0
Naimish Dixit

Andere mögliche Lösung: Ich habe versucht, das Ergebnis einer restTemplate.getForObject mit einer privaten Klasseninstanz (definiert innerhalb meiner Arbeiterklasse) abzubilden. Es hat nicht funktioniert, aber wenn ich das Objekt in einer eigenen Datei als öffentlich definiere, hat es ordnungsgemäß funktioniert.

0
Romain COMTET