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

喜欢而已 提交于 2019-12-10 13:44:33

问题


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.


回答1:


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.




回答2:


Not sure this is a good technique, and it looks like in 1.1.6 there's a different approach. Here's what i did:

@Configuration
public class WebMVCConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //Remove the Jaxb2 that is automatically added because some other dependency brings it into the classpath
        List<HttpMessageConverter<?>> baseConverters = new ArrayList<HttpMessageConverter<?>>();
        super.configureMessageConverters(baseConverters);

        for(HttpMessageConverter<?> c : baseConverters){
            if(!(c instanceof Jaxb2RootElementHttpMessageConverter)){
                converters.add(c);
            }
        }
    }

}



回答3:


if you don't want to support XML converter, you can extend spring WebMvcConfigurer to exclude XML message converters.

@Configuration
public class WebMVCConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.removeIf(c -> c instanceof AbstractXmlHttpMessageConverter<?>);
    }

}


来源:https://stackoverflow.com/questions/23480517/spring-hateoas-w-spring-boot-jaxb-marshal-error-when-returning-a-resourcest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!