Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring HATEOAS (w Spring Boot) JAXB marshal error when returning a Resources<T> or PagedResources<T> result

I've got something like this in my controller:

@RequestMapping
@ResponseBody
public HttpEntity<PagedResources<PromotionResource>> promotions(
        @PageableDefault(size = RestAPIConfig.DEFAULT_PAGE_SIZE, page = 0) Pageable pageable,
        PagedResourcesAssembler<Promotion> assembler
){

    PagedResources<PromotionResource> r = assembler.toResource(this.promoService.find(pageable), this.promoAssembler);

    return new ResponseEntity<PagedResources<PromotionResource>>(r, HttpStatus.OK);
}

If i navigate to the URL mapped to that controller method i get a 500 error with a root cause of:

com.sun.istack.internal.SAXException2: unable to marshal type "commerce.api.rest.resources.PromotionResource " as an element because it is missing an @XmlRootElement annotation 

If i throw a @XmlRootElement annotation on my resource it becomes this error:

com.sun.istack.internal.SAXException2: unable to marshal type "commerce.api.rest.resources.PromotionResource " as an element because it is not known to this context.

Everything is fine if the accept header is application/json or application/hal+json. The problem is caused only when the client (in this case chrome) is looking for application/xml (which makes sense as HATEOAS is following the clients requests. I'm using spring boot's @EnableAutoConfiguration which is adding the XML message converter to the list and thus enabling XML content types.

I'm guessing i have at least 2 options: 1. fix the jaxb error 2. remove xml as a supported content type

not sure how to do either, or maybe there's another option.

like image 747
Chris DaMour Avatar asked Oct 01 '22 21:10

Chris DaMour


1 Answers

If you don't actually want to produce XML try using the produces attribute of the @RequestMapping annotation. Something like: @RequestMapping(produces=MediaType.APPLICATION_JSON_VALUE)

Alternatively you could exclude jaxb from you classpath or look at adding your own org.springframework.boot.autoconfigure.web.HttpMessageConverters bean to take complete control of the registered HttpMessageConverter's. See WebMvcConfigurationSupport.addDefaultHttpMessageConverters to see what Spring will add by default.

like image 187
Phil Webb Avatar answered Oct 07 '22 20:10

Phil Webb