Rest Client Exception:응답을 추출할 수 없습니다.적절한 Http Message Converter를 찾을 수 없습니다.
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 파일에 저장하고 잭슨을 사용하여 해석하면 모든 것이 정상입니다.
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:f099c85d84d4e325a2186c02bd0caeef@backend.tdk.com/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)
나는 콘텐츠를 설정하려고 했다.유형:
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)
여기서의 주된 문제는 서비스로부터 수신한 콘텐츠유형 [text/carset;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);
받아들여진 답변이 OP의 원래 문제를 해결했지만, 구글 검색을 통해 이 문제를 발견한 대부분의 사람들은 완전히 다른 문제를 가지고 있을 가능성이 높다.이 문제는 적절한 Http Message Converter가 발견한 예외와 같은 문제를 던졌을 뿐이다.
비밀리에 일어나는 일은MappingJackson2HttpMessageConverter그 안에서 일어나는 모든 예외를 삼키다canRead()method: 페이로드가 json 디코딩에 적합한지 여부를 자동 검출합니다.이 예외는 기본적으로 sorry를 전달하는 단순한 부울 반환으로 대체되었습니다.이 메시지를 더 높은 수준의 API로 디코딩하는 방법을 모르겠습니다.RestClient). 다른 모든 변환기의 canRead() 메서드가 false를 반환한 후에만 적절한 HttpMessageConverter found 예외가 상위 API에 의해 느려지고 진정한 문제가 완전히 가려집니다.
못한 OP가 ), 이 은 디버거 를 에 입니다.onMappingJackson2HttpMessageConverter.canRead()그런 다음 예외에 대한 일반 중단점을 활성화하고 Continue를 누릅니다.하다
특정 오류는 콩 중 하나가 적절한 역직렬화 주석을 찾을 수 없는 인터페이스를 참조했다는 것입니다.
미래로부터의 갱신
이 문제는 많은 프로젝트에서 반복적으로 발생하고 있기 때문에 저는 보다 적극적인 솔루션을 개발했습니다.JSON을해야 할 또는 형식), JSON을 할 수 .RestTemplate콩:
public class JsonRestTemplate extends RestTemplate {
public JsonRestTemplate(
ClientHttpRequestFactory clientHttpRequestFactory) {
super(clientHttpRequestFactory);
// Force a sensible JSON mapper.
// Customize as needed for your project's definition of "sensible":
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.configure(
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter() {
public boolean canRead(java.lang.Class<?> clazz,
org.springframework.http.MediaType mediaType) {
return true;
}
public boolean canRead(java.lang.reflect.Type type,
java.lang.Class<?> contextClass,
org.springframework.http.MediaType mediaType) {
return true;
}
protected boolean canRead(
org.springframework.http.MediaType mediaType) {
return true;
}
};
jsonMessageConverter.setObjectMapper(objectMapper);
messageConverters.add(jsonMessageConverter);
super.setMessageConverters(messageConverters);
}
}
이 에 의해, 「」가 .RestClientJSON 말고는 아무것도 이해할 수 없어요장점은 발생할 수 있는 오류 메시지가 무엇이 잘못되었는지를 훨씬 더 명확하게 나타낼 수 있다는 것입니다.
비슷한 문제가 있었습니다.그것은 매우 간단한 일이었습니다.제 클라이언트는 모든 코드가 올바르게 컴파일 되었음에도 불구하고 JSON용 자동 매직 컨버터가 포함되어 있지 않았습니다.이 RestTemplate 관련 솔루션을 참조하십시오.
즉, 잭슨의 의존관계를 pom.xml에 추가했더니 효과가 있었습니다.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.1</version>
</dependency>
이 문제를 디버깅하는 한 가지 방법은 응답을 String.class로 받은 후
Gson().fromJson(StringResp.body(), MyDTO.class)
그래도 실패할 가능성이 높지만 이번에는 에러의 원인이 된 필드를 던집니다.변경 후 이전 방식을 그대로 사용할 수 있습니다.
ResponseEntity<String> respStr = restTemplate.exchange(URL,HttpMethod.GET, entity, String.class);
Gson g = new Gson();
다음 단계에서는 문제의 원인이 되고 있는 필드에 오류가 발생합니다.
MyDTO resp = g.fromJson(respStr.getBody(), MyDTO.class);
에러 메세지는 가지고 있지 않습니다만, 문제가 있는 필드를 가리키고 그 이유를 설명합니다.이러한 문제를 해결하고 이전 접근 방식을 다시 시도하십시오.
위의 @Ilya Dyoshin의 응답이 아직 취득되지 않은 경우 String Object로 응답을 가져옵니다.
(나 자신은 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);
내 경우 @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);
(Yashwant Chavan이 technical keeda라는 블로그에서 제안한 솔루션을 기반으로 합니다.)
JN 거보
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);
잭슨 데이터 바인드 패키지가 있는 공유 종속성을 추가하십시오. 이것으로 문제가 해결되기를 바랍니다.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
이렇게 하면 resttemplate와 set content를 사용하여 오브젝트 응답을 얻을 수 있습니다.다음을 사용하여 입력
public List<Employee> getListofEmployee()
{
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<Employee>> response = restTemplate.exchange("http://hello-server/rest/employees",
HttpMethod.GET,entity, new ParameterizedTypeReference<List<Employee>>() {});
return response.getBody(); //this returns List of Employee
}
내 경우 런타임 클래스 패스에 잭슨 코어, 잭슨 주석 및 잭슨 데이터 바인드 jar가 없기 때문에 발생합니다.일반적인 ClassNothFoundException이 아니라 원래 질문에서 언급된 오류에 대해 불만을 제기했습니다.
스프링은 기본 content-type을 로 설정합니다.octet-stream응답에 해당 필드가 없는 경우.메시지 컨버터를 추가하여 이 문제를 해결하기만 하면 됩니다.
기타 가능한 해결책 : restTemplate.getForObject 결과를 개인 클래스 인스턴스(작업 클래스 내에서 정의)에 매핑하려고 했습니다.동작은 하지 않았지만 오브젝트를 자신의 파일 내에서 퍼블릭하게 정의하면 정상적으로 동작했습니다.
Feign을 사용하려고 했는데, 같은 문제가 발생했기 때문에 HTTP 메시지컨버터가 도움이 될 것이라고 알고 있습니다만, 그 방법을 이해하고 싶다고 생각하고 있었습니다.
@FeignClient(name = "mobilesearch", url = "${mobile.search.uri}" ,
fallbackFactory = MobileSearchFallbackFactory.class,
configuration = MobileSearchFeignConfig.class)
public interface MobileSearchClient {
@RequestMapping(method = RequestMethod.GET)
List<MobileSearchResponse> getPhones();
}
디코더, Mobile Search Feign Config, Customer Configuration을 사용해야 합니다.
public class MobileSearchFeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
}
public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new MappingJackson2HttpMessageConverter());
return new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return httpMessageConverters;
}
};
}
public class MappingJackson2HttpMessageConverter extends org.springframework.http.converter.json.MappingJackson2HttpMessageConverter {
MappingJackson2HttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
setSupportedMediaTypes(mediaTypes);
}
}
}
내 경우 No Args 컨스트럭터가 누락되어 있었다.
@Data
@AllArgsConstructor
@NoArgsConstructor
Lombok을 사용하지 않는 사람은 맵핑 포호에 args 컨스트럭터를 추가하지 마십시오.
public ClassA() {
super();
// TODO Auto-generated constructor stub
}
또, 같은 것을 사용하고 있는 경우는, 메인 파일에 「Bean of Restemplate」를 추가하는 것도 잊지 말아 주세요.
짜증나는 문제죠?콜의 결과를 얻고 싶을 뿐이며, 시리얼화 해제 에러가 발생하고 있습니다.어디서 찾아야 할지 모르겠다는 거죠뭐, 다 잃은 건 아니에요콜 타입을 String으로 변경하면 JSON에 상당하는 것을 취득한 후 시리얼화되지 않는 이유를 확인하기 위한 테스트를 작성할 수 있습니다.
RestTemplate restTemplate = new RestTemplate();
String messageListString = restTemplate.getForObject("http://592693f43c87815f9b8145e9:f099c85d84d4e325a2186c02bd0caeef@backend.tdk.com/api/devicetypes/591570373c87894b4eece34d/messages", String.class);
다음은 Kotlin 프로젝트에서 사용한 입력 파라미터의 예입니다.
fun givenCUT_whenFetchingBillableItemsForAPastMonthWithoutBillingData_thenWeSucceedInGettingAnEmptyXmlResponse() {
val restTemplate = RestTemplate()
val uri = "http://localhost:$port/api/test/billing/xml/month/{month}/"
val params: MutableMap<String, String> = HashMap()
params["month"] = "2022-09-01"
val stringResponse = restTemplate.getForObject(uri, String::class.java, params)
assertNotNull(stringResponse)
assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<bi:billableItems xmlns:bi=\"urn:blahblahblah\"/>\n", stringResponse)
}
이 테스트를 통과하여 엔드포인트의 실제 JSON을 수집하면 다음과 같은 테스트를 사용하여 Jackson 또는 Gson이 불만을 제기하는 이유를 확인할 수 있습니다.
@Test
fun givenCUT_whenDeSerializingBEStateCorrectionsResponse_thenWeGetAnInstanceOfAListOfBillingOrdersSuccessfully() {
//Raw JSON harvested from BillingOrderControllerTest
val harvestedFEJsonBillingOrderList = "YOUR JSON Harvested from above goes here"
val mapper = ObjectMapper()
mapper.registerModule(JavaTimeModule())
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
val deSerBillingOrderList = mapper.readValue(harvestedFEJsonBillingOrderList, Array<BillingOrder>::class.java)
assertNotNull(deSerBillingOrderList)
assertEquals(1, deSerBillingOrderList.size)
}
포스트는 그만큼 쉽다...다음은 단편입니다만, 최종적으로 포기하고, 시리얼라이제이션 에러 부분을 코멘트 아웃 해, String 버전으로 되돌리고, Jackson에서 위의 테스트를 실시했습니다.지금 바로 이 순간, Jackson이 명시적으로 보고한 디시리얼라이제이션 JSON에서 4개의 문제가 발견되어 수정하겠습니다.그러면 아래를 입력된 버전으로 되돌리면 문제가 해결될 것입니다.
try {
val result = restTemplate!!.postForEntity(uri, billingOrders, String::class.java)
/* val result = restTemplate!!.postForObject(
baseUrl,
billingOrders,
ResponseEntity<List<BillingOrder>>::class.java)*/
assertNotNull(result)
} catch (e: Exception) {
log.error("Failed restTemplate.postForObject with $e")
}
언급URL : https://stackoverflow.com/questions/44176335/restclientexception-could-not-extract-response-no-suitable-httpmessageconverte
'programing' 카테고리의 다른 글
| Oracle SQL Developer 다중 테이블 보기 (0) | 2023.03.29 |
|---|---|
| 워드프레스 is_page()는 항상 false와 함께 반환됩니다. (0) | 2023.03.29 |
| 확장자가 .js인 파일에서는 JSX가 eslint-config-airbnb에서 허용되지 않습니다. (0) | 2023.03.29 |
| ReactJs에서 componentWillUnmount()를 올바르게 사용하는 방법 (0) | 2023.03.29 |
| CSS 모듈 및 리액트를 사용한 여러 클래스 이름 (0) | 2023.03.29 |