问题
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