Spring Boot WebClient XML - PullRequest
       34

Spring Boot WebClient XML

0 голосов
/ 09 апреля 2020

Моё весеннее загрузочное приложение хочет использовать Webclient для выполнения http-запроса (XML тело запроса) и получает XML ответ. Поэтому я создал другое приложение с загрузочной пружиной с помощью jackson-dataformat- xml и создал конечную точку для получения и возврата XML, как показано ниже.

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);
}

Это работает отлично, и, очевидно, аннотации JaxB не требуются, поскольку я используйте jackson-dataformat- xml. Также запрос XML может быть без учета регистра.

Теперь в моем первом приложении я хочу использовать этот API через веб-клиента. Я читал, что Spring Webflux пока не поддерживает Jackson-dataformat- xml. Следовательно, я должен аннотировать свои классы аннотациями Jaxb.

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);

Выше кода выдает исключение следующим образом

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)

Я исправил эту проблему, аннотируя XmlRootElement следующим образом

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

При следующей попытке я получил еще одну ошибку следующим образом

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

Эту проблему можно решить, пометив MyXmlResponse с помощью XmlRootElement следующим образом

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

    private String attr1;

    private String attr2;
}

На этот раз я получаю unmarshallexception как следует

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:

Я исправил это с помощью дополнительных атрибутов, переданных аннотации следующим образом.

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

В будущем мои XML структуры будут чрезвычайно сложными. Я хочу знать, правильно ли я это делаю.

...