aucun convertisseur de type HttpMessageConverter adapté n'a été trouvé pour le type de réponse
à l'Aide de printemps, avec ce code :
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for(HttpMessageConverter httpMessageConverter : messageConverters){
System.out.println(httpMessageConverter);
}
ResponseEntity<ProductList> productList = restTemplate.getForEntity(productDataUrl,ProductList.class);
je
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]
un extrait de la pojo :
@XmlRootElement(name="TheProductList")
public class ProductList {
@XmlElement(required = true, name = "date")
private LocalDate importDate;
9 réponses
du point de vue du printemps, aucun des HttpMessageConverter
instances enregistrées avec le RestTemplate
peut convertir text/html
contenu ProductList
objet. La méthode d'intérêt est HttpMessageConverter#canRead(Class, MediaType)
. La mise en œuvre de tous les ci-dessus renvoie false
Jaxb2RootElementHttpMessageConverter
.
Depuis pas HttpMessageConverter
peut lire votre réponse HTTP, le traitement échoue avec une exception.
si vous pouvez contrôler la réponse du serveur, Modifiez - la pour définir le Content-type
application/xml
,text/xml
, ou quelque chose correspondant à application/*+xml
.
si vous ne contrôlez pas la réponse du serveur, vous devrez écrire et enregistrer votre propre HttpMessageConverter
(qui peut étendre les classes de ressorts, voir AbstractXmlHttpMessageConverter
et ses sous-classes) qui peut lire et convertir text/html
.
si vous ne pouvez pas modifier la réponse de type média du serveur, vous pouvez étendre GsonHttpMessageConverter pour traiter des types de support supplémentaires
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);
}
}
si vous utilisez Spring Boot, vous pourriez vouloir vous assurer que vous avez la dépendance Jackson dans votre chemin de classe. Vous pouvez le faire manuellement via:
<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>
Ou vous pouvez utiliser le web starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
vous pouvez créer une classe, RestTemplateXML, qui étend RestTemplate. Alors outrepassez doExecute(URI, HttpMethod, RequestCallback, ResponseExtractor<T>)
, et explicitement get response-headers
et définissez content-type
application/xml
.
maintenant Spring lit les en-têtes et sait qu'il est `application/xml'. C'est un peu un piratage, mais ça marche.
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);
}
}
essaye ceci:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.0</version>
</dependency>
en plus de toutes les réponses, si vous recevez une réponse text/html
alors que vous vous attendiez à autre chose (i.e. application/json
), cela peut suggérer qu'une erreur s'est produite du côté du serveur (disons 404) et que la page d'erreur a été retournée au lieu de vos données.
Donc ça c'est passé dans mon cas. Espérons qu'il permettra de sauver quelqu'un.
Ou vous pouvez utiliser
public void setSupportedMediaTypes (Listsupportedmediatypes)
méthode qui appartient à AbstractHttpMessageConverter<T>
ajouter ContentTypes
vous le souhaitez. De cette façon, peut laisser l' MappingJackson2HttpMessageConverter
canRead()
votre réponse, et la transformer à votre classe désirée,qui sur ce cas, est la classe ProductList.
et je pense que cette étape devrait être raccordée avec le contexte Spring initialisant. par exemple, en utilisant
met en œuvre ApplicationListener { ... }
Un raffinement de réponse de Vadim Zin4uk est juste pour utiliser la classe GsonHttpMessageConverter existante mais invoquer le setsupportedmediatypes () setter.
pour les applications de démarrage de printemps, cela se traduit par un ajout à la liste suivante de vos classes de configuration:
@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;
}
ce n'est pas répondre au problème mais si quelqu'un vient à cette question quand ils trébuchent sur cette exception d'aucun convertisseur de message approprié trouvé, voici mon problème et la solution.
Au Printemps 4.0.9, nous avons été en mesure d'envoyer ce
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);
au printemps 4.3.5 libération, nous commençons à voir des erreurs avec le message que le convertisseur n'a pas été trouvé. La façon dont COnverets fonctionne est que si vous l'avez dans votre chemin de classe, ils sont enregistrés.jackson-asl était encore en classe. mais n'a pas été reconnu par le printemps. Nous remplaçons Jackson-asl par plus rapide-XML jackson core. Une fois que nous avons ajouté, je pouvais voir le convertisseur enregistré