json - headers - RestClientException: No se pudo extraer la respuesta. no se ha encontrado un HttpMessageConverter adecuado
resttemplate timeout (6)
Usando el comando curl:
curl -u 591bf65f50057469f10b5fd9:0cf17f9b03d056ds0e11e48497e506a2 https://backend.tdk.com/api/devicetypes/59147fd79e93s12e61499ffe/messages
Estoy recibiendo una respuesta JSON:
{"data":[{"device":"18SE62","time":1494516023,"data":"3235","snr":"36.72",...
Guardo la respuesta en un archivo txt y lo analizo usando jackson, y todo está bien
ObjectMapper mapper = new ObjectMapper();
File f = new File(getClass().getResource
("/result.json").getFile());
MessageList messageList = mapper.readValue(f, MessageList.class);
y supongo que debería obtener el mismo resultado utilizando RestTemplate pero no es el caso
RestTemplate restTemplate = new RestTemplate();
MessageList messageList =
restTemplate.getForObject("http://592693f43c87815f9b8145e9:[email protected]/api/devicetypes/591570373c87894b4eece34d/messages", MessageList.class);
Tengo un error en su lugar
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)
Intenté establecer el tipo de contenido:
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);
Pero luego tengo un error de compilación
The method getForObject(String, Class<T>, Object...) in the type RestTemplate is not applicable for the arguments (String, HttpEntity<String>,
Class<MessageList>)
También intenté agregar un convertidor de mensajes de Jackson.
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);
Pero entonces tengo este error:
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)
También intenté agregar la clase
@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;
}
}
pero me salió el error
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)
El problema principal aquí es el tipo de contenido [text / html; charset = iso-8859-1] recibido del servicio, sin embargo, el tipo de contenido real debe ser application / json; charset = iso-8859-1
Para superar esto puedes introducir un convertidor de mensajes personalizado. y registrarlo para todo tipo de respuestas (es decir, ignorar el encabezado de tipo de contenido de respuesta). Como esta
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(Arrays.asList({MediaType.ALL}));
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
En mi caso, fue causado por la ausencia de los tarros jackson-core, jackson-notation y jackson-databind de classpath en tiempo de ejecución. No se quejó con la excepción habitual ClassNothFoundException como se podría esperar, sino con el error mencionado en la pregunta original.
En mi caso, la solución de @Ilya Dyoshin no funcionó: el tipo de medio "*" no estaba permitido. Arreglo este error agregando un nuevo convertidor a restTemplate de esta manera durante la inicialización de MockRestServiceServer:
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
Arrays.asList(
MediaType.APPLICATION_JSON,
MediaType.APPLICATION_OCTET_STREAM));
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
mockServer = MockRestServiceServer.createServer(restTemplate);
(Basado en la solución propuesta por Yashwant Chavan en el blog llamado technicalkeeda)
JN Gerbaux
Estaba teniendo un problema muy similar, y resultó ser bastante simple; mi cliente no estaba incluyendo una dependencia de Jackson, a pesar de que todo el código se compiló correctamente, los convertidores de auto-magia para JSON no estaban incluidos. Vea esta solución relacionada con RestTemplate.
En resumen, agregué una dependencia de Jackson a mi pom.xml y simplemente funcionó:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.1</version>
</dependency>
Si bien la respuesta aceptada resolvió el problema original del OP, sospecho que la mayoría de las personas que encuentran esta pregunta a través de una búsqueda en Google probablemente (estadísticamente hablando) tengan un problema completamente diferente, lo que simplemente produce la misma excepción no adecuada para HttpMessageConverter .
Lo que sucede debajo de las coberturas es que MappingJackson2HttpMessageConverter
traga cualquier excepción que ocurra en su método canRead()
, que se supone que detecta automáticamente si la carga útil es adecuada para la decodificación json. La excepción se reemplaza por un simple retorno booleano que básicamente se comunica con "lo siento", no sé cómo decodificar este mensaje a las API de nivel superior ( RestClient
) Solo después de que todos los otros métodos canRead () de los convertidores devuelvan el valor falso, la API de nivel superior no arroja la excepción de HttpMessageConverter adecuada , ocultando totalmente el verdadero problema.
Para las personas que no han encontrado la causa raíz (como usted y yo, pero no el OP), la forma de solucionar este problema es colocar un punto de ruptura del depurador en onMappingJackson2HttpMessageConverter.canRead()
, luego habilitar un punto de interrupción general en cualquier excepción, y pulsa Continuar. La siguiente excepción es la verdadera causa raíz.
Mi error específico fue que uno de los beans hacía referencia a una interfaz a la que le faltaban las anotaciones de deserialización adecuadas.
Si la respuesta anterior de @Ilya Dyoshin aún no se recuperó, intente obtener la respuesta en un objeto String.
(Para mi propio pensamiento, el error se resolvió mediante el fragmento de código de Ilya, la respuesta recuperada fue un error (error) del servidor).
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);
Y lanzar al ResponseObject DTO (Json)
Gson g = new Gson();
DTO dto = g.fromJson(st.getBody(), DTO.class);