6 votes

Org.springframework.web.reactive.function.UnsupportedMediaTypeException: Type de contenu 'text/xml;charset=UTF-8' non pris en charge pour bodyType

En utilisant Java 11, SpringBoot 2, WebFlux, WebClient et Jackson

en essayant d'utiliser Spring WebClient pour consommer un point de terminaison de service Web qui renvoie du XML, type de contenu: 'text/xml;charset=UTF-8'

Dépendance Jackson XML dans le fichier pom.xml du projet:

    com.fasterxml.jackson.dataformat
    jackson-dataformat-xml
    2.9.9

Code WebClient qui déclenche une demande à une API externe et construit la réponse:

        WebClient.builder()
                .baseUrl(url)
                .build()
                .get()
                .uri(builder.toUriString(), 1L)
                .accept(TEXT_XML)
                .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML_VALUE)
                .acceptCharset(Charset.forName("UTF-8"))
                .exchange()
                .flatMap(x -> x.bodyToMono(ServiceResponse.class))
                .flatMap(x -> buildResponse(x));

Classe ServiceResponse (un simple POJO):

public class ServiceResponse {

    private String ack;
    private String version;
    private String timestamp;
// .. getters and setters

erreur résultante:

org.springframework.web.reactive.function.UnsupportedMediaTypeException: Type de contenu 'text/xml;charset=UTF-8' non pris en charge pour bodyType=com.sample.service.model.ServiceResponse at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na] at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:197) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$2(BodyExtractors.java:85) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:95) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.web.reactive.function.client.DefaultClientResponse.bodyToMono(DefaultClientResponse.java:113) ~[spring-webflux-5.1.8.RELEASE.jar:5.1.8.RELEASE]

comment consommer correctement le type de réponse : Content-type 'text/xml;charset=UTF-8' ?

2voto

Brian Clozel Points 6473

Jackson XML n'est pas pris en charge pour le moment par Spring Framework - voir le problème dédié. En attendant, vous pouvez utiliser Jaxb avec Jaxb2XmlEncoder et Jaxb2XmlDecoder.

1voto

Boney Points 528

Ajouter

.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) 

a fonctionné pour moi. MediaType représente le type de média Internet défini dans la spécification HTTP. Pour référence : https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/MediaType.html

Lorsque j'essayais d'écrire un cas de test en utilisant WebTestClient dans spring webflux, j'ai rencontré cette erreur. Le test unitaire se trouve dans la section suivante :

@Test
 public void testGetJobSummariesResBody() throws Exception{
 List responseBody = testClient
                .get().uri("")
                .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
                .header(APPNAME_HEADER, "")
                .exchange()
                .expectStatus().isOk()
                .expectBodyList(JobSummary.class)
                .returnResult()
                .getResponseBody();

        assertNotNull(responseBody.get(0).getJobType());
        assertNotEquals(0,responseBody.size());
    }

0voto

J'ai eu un cas similaire, quand j'essayais de retourner "plain/text" mais l'objet était résolu en format json (donc pas vraiment un texte). Je suppose que Spring faisait une certaine validation du type de contenu de la réponse et du corps que vous avez défini. Ma réponse actuelle était comme ça:

Mono.just(quote.getQuote())
                .flatMap(s -> ServerResponse.ok()
                        .contentType(MediaType.TEXT_PLAIN)
                        .syncBody(s)
                );

mais aussi acceptable était:

Mono.just(jsonQuote)
                .flatMap(s -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .syncBody(s)
                );

0voto

JohnEye Points 3070

Dans mon cas, le problème était que j'avais oublié de définir l'en-tête Accept et le comportement par défaut du serveur était de renvoyer du XML.
En le définissant sur MediaType.APPLICATION_JSON, le problème a été résolu et le serveur a commencé à renvoyer du JSON.

0voto

Olavi Vaino Points 98

Une autre situation dans laquelle UnsupportedMediaTypeException est déclenchée. Supposons qu'il existe une API de production qui écoute à la fois sur http/80 et https/443. Cependant, elle est configurée de sorte qu'aucun contenu ne soit servi via http. Au lieu de cela, cela renvoie un message de redirection HTTP 301 avec un contenu html ayant un contenu de type text/html. Par défaut, WebClient ne suit pas la redirection 301 et essaie plutôt de parser le message html renvoyé dans la classe supposée. Cela échoue évidemment et produit une exception UnsupportedMediaTypeException. Cela peut être encore plus confus par le fait que Postman suit par défaut la redirection 301 et le fait de manière complètement transparente. Laissant l'impression que vous obtenez le contenu attendu via la demande http.

Solution : utiliser une demande https.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X