web-dev-qa-db-ja.com

RestClientException:応答を抽出できませんでした。適切なHttpMessageConverterが見つかりません

Curlコマンドの使用:

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

JSON応答を取得しています:

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

応答をtxtファイルに保存し、jacksonを使用して解析します。すべて問題ありません

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

restTemplateを使用しても同じ結果が得られるはずですが、そうではありません

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

代わりにエラーが発生しました

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)

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

しかし、その後、コンパイルエラーが発生しました

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

また、Jackson Messageコンバーターを追加しようとしました

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

しかし、私はこのエラーを受け取りました:

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)

クラスを追加してみました

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

}

しかし、私はエラーを得ました:

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

ここでの主な問題は、コンテンツタイプ[text/html; charset = iso-8859-1]サービスから受信したものですが、実際のコンテンツタイプはapplication/json; charset = iso -8859-1

これを克服するために、カスタムメッセージコンバーターを導入できます。あらゆる種類の応答に対して登録します(つまり、応答コンテンツタイプヘッダーを無視します)。ちょうどこのような

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

私は非常によく似た問題を抱えていましたが、それは非常に簡単なことがわかりました。コードがすべてcompiled正しくコンパイルされていても、JSONの自動マジックコンバーターは含まれていませんでしたが、私のクライアントにはJackson依存関係が含まれていませんでした。 このRestTemplate関連のソリューションを参照してください。

要するに、pom.xmlにJackson依存関係を追加しましたが、うまくいきました。

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

受け入れられた答えはOPの元の問題を解決しましたが、Google検索でこの質問を見つけるほとんどの人は(統計的に言えば)まったく同じ問題を起こす可能性があります HttpMessageConverter found例外。

内部で起こることは、MappingJackson2HttpMessageConvertercanRead()メソッドで発生する例外を飲み込むことです。これは、ペイロードがjsonデコードに適しているかどうかを自動検出することになっています。例外は、基本的にを通信する単純なブール値の戻り値に置き換えられます。申し訳ありませんが、このメッセージをデコードする方法がわかりません上位API(RestClient)。他のすべてのコンバーターのcanRead()メソッドがfalseを返した後にのみ、no適切なHttpMessageConverter found例外が上位APIによってスローされ、真の問題を完全に覆い隠します。

根本的な原因を見つけていない人(あなたと私など、しかしOPは見つけられない)の場合、この問題をトラブルシューティングする方法は、onMappingJackson2HttpMessageConverter.canRead()にデバッガブレークポイントを配置し、例外で一般的なブレークポイントを有効にすることです。続行をクリックします。次の例外は真の根本原因です。

私の特定のエラーは、Beanの1つが適切な逆シリアル化アノテーションが欠落しているインターフェースを参照したことでした。

13
Alex R

@ Ilya Dyoshinによる上記の応答がまだ取得されない場合は、応答を文字列オブジェクトに取得してみてください。

(私の考えでは、エラーはIlyaのコードスニペットによって解決されたと考えられ、取得された応答はサーバーからの失敗(エラー)でした。)

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

ResponseObject DTO(Json)へのキャスト

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

私の場合、@ Ilya Dyoshinのソリューションは機能しませんでした。メディアタイプ「*」は許可されませんでした。 MockRestServiceServerの初期化中に、この方法でrestTemplateに新しいコンバーターを追加することにより、このエラーを修正します。

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

(technicalkeedaという名前のブログでYashwant Chavanが提案したソリューションに基づく)

JNジェルボー

2
JN Gerbaux

私の場合、ランタイムクラスパスにjackson-core、jackson-annotations、およびjackson-databind jarがないことが原因でした。予想されるような通常のClassNothFoundExceptionではなく、元の質問で言及されたエラーで文句を言いました。

1
ikolomiyets

GET要求を行う前に、独自のコンバーターを作成して実装する必要があります。

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

その他の可能な解決策:restTemplate.getForObjectの結果をプライベートクラスインスタンス(作業クラス内で定義)にマップしようとしました。それは機能しませんでしたが、オブジェクトをそれ自身のファイル内でパブリックに定義すると、正しく機能しました。

0
Romain COMTET