Spring Boot WebClient XML
Asked Answered
F

0

7

My spring boot application wants to use Webclient to make an http request (XML request body) and receives XML response. Hence I created another spring boot application with jackson-dataformat-xml and created an endpoint to receive and return XML as below.

spring-boot-version=2.2.5
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

@PostMapping(value = "/api",
            consumes = MediaType.APPLICATION_XML_VALUE,
            produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MyXmlResponse> trip(@RequestBody MyXmlRequest request) throws Exception {
   MyXmlResponse response = new MyXmlResponse();
   response.setStatus("SUCCESS");
   response.setTripID(request.getTripID());
   return ResponseEntity.ok().body(response);
}

It works perfect and obviously no JaxB annotations are required as I use jackson-dataformat-xml. Also the request XML can be case-insensitive.

Now, in my first application I want to consume this API via webclient. I read that Spring webflux do not support Jackson-dataformat-xml yet. Hence I have to annotate my classes with Jaxb annotations.

spring-boot-version=2.2.5
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

webClient.post()
.uri(URI.create("url-to-api-endpoint"))
.body(Mono.just(myXmlRequest), MyXmlRequest.class)
.exchange()
.doOnSuccess(response -> {
    HttpStatus statusCode = response.statusCode();
    log.info("Status code of external system request {}", statusCode);
})
.doOnError(onError -> {
    log.error("Error on connecting to external system {}", onError.getMessage());
})
.flatMap(response -> response.bodyToMono(MyXmlResponse.class))
.subscribe(this::handleResponse);

Above code throws an exception as follows

org.springframework.webreactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlRequest
    at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391)

I fixed this problem by annotating with XmlRootElement as follows

@Getter @Setter @NoArgsConstructor @ToString
@XmlRootElement()
public class MyXmlRequest {
    private String attribute1;
}

On the next attempt I got another error as follows

reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse
Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse

This could be solved by annotating MyXmlResponse with XmlRootElement as follows

@Getter @Setter @NoArgsConstructor @ToString
@XmlRootElement()
public class MyXmlResponse {

    private String attr1;

    private String attr2;
}

This time I get unmarshallexception as follows

reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
 - with linked exception:
[com.sun.istack.internal.SAXParseException2; lineNumber: 1; columnNumber: 15; unexpected element (uri:"", local:"MyXmlResponse"). Expected elements are <{}myXmlResponse>]
Caused by: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
 - with linked exception:

I fixed it with additional attributes passed to annotation as follows.

@XmlRootElement(name = "MyXmlResponse", namespace = "")
public class MyXmlResponse {

In future, my XML structures going to be tremendously complex. I want to know if I am doing it the right way.

Forage answered 9/4, 2020 at 7:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.