返回Resources <t>或PagedResources <t>结果时,Spring HATEOAS(w Spring Boot)JAXB编组错误</t> </t>

时间:2014-05-05 19:45:30

标签: spring-boot spring-hateoas

我的控制器里有这样的东西:

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

如果我导航到映射到该控制器方法的URL,则会出现500错误,其根本原因为:

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

如果我在我的资源上抛出@XmlRootElement注释,则会出现此错误:

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.

如果accept标头是application / json或application / hal + json,那么一切都很好。只有当客户端(在本例中为chrome)正在寻找application / xml时才会出现问题(这在HATEOAS遵循客户端请求时是有意义的。我使用spring boot&#39; @EnableAutoConfiguration,它正在添加XML消息转换器到列表,从而启用XML内容类型。

我猜我至少有两个选择: 1.修复jaxb错误 2.删除xml作为支持的内容类型

不确定如何做,或者可能还有其他选择。

3 个答案:

答案 0 :(得分:4)

如果您实际上不想生成XML,请尝试使用produces注释的@RequestMapping属性。类似于:@RequestMapping(produces=MediaType.APPLICATION_JSON_VALUE)

或者,您可以从类路径中排除jaxb,或者查看添加自己的org.springframework.boot.autoconfigure.web.HttpMessageConverters bean以完全控制已注册的HttpMessageConverter。请参阅WebMvcConfigurationSupport.addDefaultHttpMessageConverters以查看Spring默认添加的内容。

答案 1 :(得分:1)

不确定这是一项好技术,看起来在1.1.6中有一种不同的方法。这就是我所做的:

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

}

答案 2 :(得分:0)

如果您不想支持XML转换器,则可以扩展spring WebMvcConfigurer以排除XML消息转换器。

@Configuration
public class WebMVCConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {

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

}