복붙노트

[SPRING] 응답 유형에 적합한 HttpMessageConverter가 없습니다.

SPRING

응답 유형에 적합한 HttpMessageConverter가 없습니다.

이 코드와 함께 spring을 사용하면 :

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

나는 얻다

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]

pojo의 발췌 문장 :

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

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

해결법

  1. ==============================

    1.Spring의 관점에서, RestTemplate에 등록 된 HttpMessageConverter 인스턴스 중 어느 것도 text / html 콘텐츠를 ProductList 객체로 변환 할 수 없습니다. 해당 메소드는 HttpMessageConverter # canRead (Class, MediaType)입니다. 위의 모든 것에 대한 구현은 Jaxb2RootElementHttpMessageConverter를 포함하여 false를 반환합니다.

    Spring의 관점에서, RestTemplate에 등록 된 HttpMessageConverter 인스턴스 중 어느 것도 text / html 콘텐츠를 ProductList 객체로 변환 할 수 없습니다. 해당 메소드는 HttpMessageConverter # canRead (Class, MediaType)입니다. 위의 모든 것에 대한 구현은 Jaxb2RootElementHttpMessageConverter를 포함하여 false를 반환합니다.

    HttpMessageConverter는 HTTP 응답을 읽을 수 없기 때문에 처리가 실패하고 예외가 발생합니다.

    서버 응답을 제어 할 수있는 경우 Content-type을 application / xml, text / xml 또는 application / * + xml과 일치하는 것으로 설정하도록 수정하십시오.

    서버 응답을 제어하지 않으면 text / html을 읽고 변환 할 수있는 HttpMessageConverter (Spring 클래스를 확장 할 수있는 AbstractXmlHttpMessageConverter 및 해당 하위 클래스 참조)를 작성하고 등록해야합니다.

  2. ==============================

    2.서버 미디어 유형 응답을 변경할 수없는 경우 GsonHttpMessageConverter를 확장하여 추가 지원 유형을 처리 할 수 ​​있습니다

    서버 미디어 유형 응답을 변경할 수없는 경우 GsonHttpMessageConverter를 확장하여 추가 지원 유형을 처리 할 수 ​​있습니다

    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);
        }
    }
    
  3. ==============================

    3.Spring Boot를 사용한다면 클래스 패스에 Jackson 종속성이 있는지 확인하는 것이 좋습니다. 다음을 통해이 작업을 수동으로 수행 할 수 있습니다.

    Spring Boot를 사용한다면 클래스 패스에 Jackson 종속성이 있는지 확인하는 것이 좋습니다. 다음을 통해이 작업을 수동으로 수행 할 수 있습니다.

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

    또는 웹 스타터를 사용할 수 있습니다.

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
  4. ==============================

    4.RestTemplate을 확장하는 RestTemplateXML 클래스를 만들 수 있습니다. 그런 다음 doExecute (URI, HttpMethod, RequestCallback, ResponseExtractor )를 무시하고 명시 적으로 응답 헤더를 가져 와서 content-type을 application / xml로 설정합니다.

    RestTemplate을 확장하는 RestTemplateXML 클래스를 만들 수 있습니다. 그런 다음 doExecute (URI, HttpMethod, RequestCallback, ResponseExtractor )를 무시하고 명시 적으로 응답 헤더를 가져 와서 content-type을 application / xml로 설정합니다.

    이제 Spring은 헤더를 읽고`application / xml '이라는 것을 알고있다. 그것은 일종의 해킹이지만 작동합니다.

    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);
      }
    }
    
  5. ==============================

    5.이 시도:

    이 시도:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.0</version>
    </dependency>
    
  6. ==============================

    6.모든 답변 외에도, 뭔가 다른 (예 : 응용 프로그램 / json)을 기대하는 동안 text / html로 응답을 받으면 서버 측에서 오류가 발생했으며 (404) 오류 페이지가 표시 될 수 있습니다 귀하의 데이터 대신에 반환되었습니다.

    모든 답변 외에도, 뭔가 다른 (예 : 응용 프로그램 / json)을 기대하는 동안 text / html로 응답을 받으면 서버 측에서 오류가 발생했으며 (404) 오류 페이지가 표시 될 수 있습니다 귀하의 데이터 대신에 반환되었습니다.

    내 사건에서 그렇게 된거야. 누군가의 시간을 절약하기를 바랍니다.

  7. ==============================

    7.또는 사용할 수 있습니다.

    또는 사용할 수 있습니다.

    AbstractHttpMessageConverter 에 속한 메서드를 사용하여 원하는 ContentTypes를 추가 할 수 있습니다. 이 방법을 사용하면 MappingJackson2HttpMessageConverter가 응답을 canRead () 할 수 있으며 원하는 Class (이 경우 ProductList 클래스)로 변환 할 수 있습니다.

    이 단계는 스프링 컨텍스트 초기화로 연결되어야한다고 생각합니다. 예를 들어

  8. ==============================

    8.Vadim Zin4uk의 대답은 기존 GsonHttpMessageConverter 클래스를 사용하지만 setSupportedMediaTypes () setter를 호출하는 것입니다.

    Vadim Zin4uk의 대답은 기존 GsonHttpMessageConverter 클래스를 사용하지만 setSupportedMediaTypes () setter를 호출하는 것입니다.

    스프링 부팅 응용 프로그램의 경우 구성 클래스에 다음과 같이 추가됩니다.

    @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;
    }
    
  9. ==============================

    9.이것은 문제에 대한 답변이 아니지만 누군가 적절한 메시지 변환기가 없다는 예외에 비틀 거 렸을 때이 질문에 오는 경우 여기에 내 문제와 해결책이 있습니다.

    이것은 문제에 대한 답변이 아니지만 누군가 적절한 메시지 변환기가 없다는 예외에 비틀 거 렸을 때이 질문에 오는 경우 여기에 내 문제와 해결책이 있습니다.

    Spring 4.0.9에서 우리는 이것을 보낼 수 있었다.

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

    Spring 4.3.5 릴리스에서는 변환기가 없다는 메시지와 함께 오류가 발생하기 시작했다. COnverets가 작동하는 방식은 클래스 패스에 있으면 등록되어 있습니다 .jackson-asl은 여전히 ​​클래스 패스에 있지만 봄까지는 인식되지 않았습니다. 우리는 Jackson-asl을보다 빠른 xml jackson core로 대체합니다. 일단 우리는 변환기가 등록 된 것을 볼 수있었습니다.

  10. from https://stackoverflow.com/questions/21854369/no-suitable-httpmessageconverter-found-for-response-type by cc-by-sa and MIT license