question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support XML Marshalling with jackson-dataformat-xml in WebFlux [SPR-15697]

See original GitHub issue

Jarno Walgemoed opened SPR-15697 and commented

Hi,

Jackson-xml marshalling seems to be broken in the 2.0.0 M2 milestone release for Spring boot which contains Spring 5.0 RC2 (with web-flux). I tried both with functional web routers and a ‘classic’ (simple) annotation based controller (in Kotlin):

data class Hello(val one: String, val two: String)

@Bean
fun apiRouter() = router {
    GET("/hello") { req ->
        ok().contentType(MediaType.APPLICATION_XML)
                .body(BodyInserters.fromObject(Hello("Hello", "World")))
    }
}

And

data class Hello(val one: String, val two: String)

@RestController
class HelloController {
    @GetMapping("/hello") fun sayHello() = Hello("Hello", "World")
}

The jackson XML marshaller doesn’t seem to be registered automatically anymore.

Steps to reproduce

  • Create a Spring Boot project (start.spring.io) -> 2.0.0 M2 with the reactive web dependency;
  • Add a restcontroller that returns a simple entity (see above);
  • Add jackson-dataformat-xml dependency.

Call the endpoint with the application/xml accept header. The sever will respond with a 406 - not acceptable response. In the logging this shows up:

2017-06-23 12:39:42.629 ERROR 26064 --- [ctor-http-nio-2] o.s.w.s.h.ResponseStatusExceptionHandler : Response status 406 with reason "Could not find acceptable representation"

Verification

I’ve tried a similar approach with the latest stable Spring version and there it works as expected, depending on the provided accept header (application/xml or application/json) the application responds with the response in the requested format.


Affects: 5.0 RC2

3 votes, 6 watchers

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:15
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
csapty12commented, Nov 26, 2019

I have managed to find a solution to this:

Firstly, I created a bean to encode and decode the XML:

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        return WebClient
        .builder()
        .baseUrl("Your base URL here")
        .exchangeStrategies(ExchangeStrategies.builder().codecs((configurer) -> {
            configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
            configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder());
        }).build())
    .build();
    }
}

This enables you to encode and decode the xml request and responses.

In the request object that I want to convert to XML before sending it, I added the @XmlRootElement(name="MyElement")

@XmlRootElement(name="MyElementRequestObject")
public class MyElementRequestObject {
}

By default, if you do not add in the name field on the XMLRootElement, it will make your xml into lowercase ( see https://stackoverflow.com/questions/9879433/jaxb-java-generating-xml-why-lowercase)

In my response object, I did something similar:

@NoArgsConstructor
@Getter
@ToString
@XmlRootElement(name = "MyElementResponseObject")
public class MyElementResponseObject {

    @XmlElement(name = "data")
    private List<String> listOfData;
}

Finally, putting it altogether, I can now make my post() request as needed:

 MyElementResponseObject block = webClient.post()
                .uri("your endpoint name here")
                .syncBody(new MyElementRequestObject())
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
                .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
                .retrieve()
                .bodyToMono(MyElementResponseObject.class)
                .block();

        System.out.println("string returned: " + block.toString()); //just to test it worked

This enabled me to not have to return the result as an object, rather than a string.

Hope that helps!

2reactions
Sergey80commented, Feb 7, 2019

ok. if annotate my object woth jaxb-annotation (@XmlRootElement()) it works ok for the post-body (.body(Mono.just(requestClientData), RequestClientData.class)), but: .bodyToMono(MyClass.class) - response returns alway null object. Have to use .bodyToMono(String.class). Is there a workaround for this? Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

SpringBoot Webflux cannot return application/xml
Apparently, jackson-dataformat-xml does not yet support XML Marshalling in WebFlux. As for now I see two possibilities:.
Read more >
Solving the XML Problem with Jackson - Stackify
For example, marshalling some object to XML is done simply by using the ... The Jackson XML module adds some additional support for...
Read more >
Solving the XML Problem with Jackson - DZone
Supporting JAXB Annotations. The Jackson XML module also has the ability to support the standard JAXB annotations on our beans – instead of ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found