2014-04-23 690 views
5

Próbuję użyć spring-data-mongodb z spring-hateoas i otrzymuję wyjątek javax.xml.bind.MarshalException podczas testowania. Jak mogę obejść ten problem? Czy brakuje adnotacji lub innych kroków?Dlaczego następujący Spring Boot + HATEOAS z mongodb nie działa (MarshalException)?

mój pom:

<dependency> 
    <groupId>org.springframework.hateoas</groupId> 
    <artifactId>spring-hateoas</artifactId> 
</dependency> 
<dependency> 
    <groupId>org.springframework.plugin</groupId> 
    <artifactId>spring-plugin-core</artifactId> 
    <version>1.0.0.RELEASE</version> 
</dependency>    

Mój "UserResourceAssembler.java":

@Component 
class UserResourceAssembler implements ResourceAssembler<User, Resource<User>> { 

    String customersRel = "customers"; 

    @Override 
    public Resource<User> toResource(MyObj u) { 

     try { 
      User user = new User("John"); 
      Collection<Link> links = new ArrayList<Link>();    
      return new Resource<User>(user, links); 
     } 
     catch (Exception throwable) { 
      throw new RuntimeException(throwable); 
     } 
    } 
} 

Mój "User.java" reprezentujący dokument MongoDB:

@Document 
@XmlRootElement(name="user") 
public class User { 
    @Id 
    private String id; 

    private String occupation; 

    public User() {} 
    public User(String occupation) { 
    this.occupation = occupation; 
    } 

    @Override 
    public String toString() { 
return String.format(  
       "{id:%s, occupation='%s'}", 
       ttid, occupation); 
     } 


} 

Mój „UserController. java ":

@RestController 
@ExposesResourceFor(User.class) 
@RequestMapping(value = "/users") 
public class UserController { 
    @Autowired 
    UserResourceAssembler userResourceAssembler; 


    @RequestMapping(method = RequestMethod.GET, value = "/name/{user}") 
    Resource<User> testUser(@PathVariable String user) { 
     return userResourceAssembler.toResource(new User("Teenager")); 
    } 
} 

W moim Application.java I obejmował następujące adnotacje:

@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL) 

Mój problem jest dlaczego otrzymuję błąd podczas odwiedzania:

http://localhost:8080/users/name/doesnotmatterrightnow 

Problem w oparciu o komunikat o błędzie z linia:

return userResourceAssembler.toResource(new User("Teenager")); 

Poniżej znajduje się pełny błąd:

HTTP Status 500 - Could not marshal [Resource { content: {id:null, occupation='Teenager'}, links: [] }]: null; nested exception is javax.xml.bind.MarshalException 

type Exception report 

message Could not marshal [Resource { content: {id:null, occupation='Teenager'}, links: [] }]: null; nested exception is javax.xml.bind.MarshalException 

description The server encountered an internal error that prevented it from fulfilling this request. 

exception 

org.springframework.http.converter.HttpMessageNotWritableException: Could not marshal [Resource { content: {id:null, occupation='Teenager'}, links: [] }]: null; nested exception is javax.xml.bind.MarshalException 
- with linked exception: 
[com.sun.istack.internal.SAXException2: class sample.User nor any of its super class is known to this context. 
javax.xml.bind.JAXBException: class sample.User nor any of its super class is known to this context.] 
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.writeToResult(Jaxb2RootElementHttpMessageConverter.java:138) 
    org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:66) 
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:207) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:148) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90) 
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193) 
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
root cause 

javax.xml.bind.MarshalException 
- with linked exception: 
[com.sun.istack.internal.SAXException2: class sample.User nor any of its super class is known to this context. 
javax.xml.bind.JAXBException: class sample.User nor any of its super class is known to this context.] 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311) 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) 
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.writeToResult(Jaxb2RootElementHttpMessageConverter.java:135) 
    org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:66) 
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:207) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:148) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90) 
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193) 
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
root cause 

com.sun.istack.internal.SAXException2: class sample.User nor any of its super class is known to this context. 
javax.xml.bind.JAXBException: class sample.User nor any of its super class is known to this context. 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:235) 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:250) 
    com.sun.xml.internal.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:102) 
    com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343) 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582) 
    com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:325) 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483) 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) 
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.writeToResult(Jaxb2RootElementHttpMessageConverter.java:135) 
    org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:66) 
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:207) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:148) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90) 
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193) 
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
root cause 

javax.xml.bind.JAXBException: class sample.User nor any of its super class is known to this context. 
    com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:572) 
    com.sun.xml.internal.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:94) 
    com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343) 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582) 
    com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:325) 
    com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483) 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) 
    com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) 
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.writeToResult(Jaxb2RootElementHttpMessageConverter.java:135) 
    org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:66) 
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:207) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:148) 
    org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:90) 
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193) 
    org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) 
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) 
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108) 
+0

Czy jesteś pewien, że userResourceAssembler jest wtryskiwany do UserController klasy, ponieważ nie używać żadnych adnotacji na polu? – Taky

+0

Automatyczne uzbrojenie wygląda na to, że kontroler widzi to, ale nie jest w stanie "wymusić" wypluwania wyjątku MarshalException. – Rolando

Odpowiedz

1

Myślę, że brakowało @XmlElement na klasy User

Edit1

mam to Resource.java nie mają @XmlSeeAlso dla klasy User JAXB więc nie można go znaleźć w kontekście ty może użyć poniższego UserResource i zastąpić wszystkie zasoby tą nową klasą, działa teraz.

@XmlRootElement 
@XmlSeeAlso({User.class}) 
public class UserResource extends Resource<User> { 

    public UserResource() { 
     this(new User(),null); 
    } 

    public UserResource(User content, Iterable<Link> links) { 
     super(content, links); 
    } 
} 
+0

Zaktualizowany post, próbowałem atXmlRootElement powyżej klasy User, ale ten sam MarshalException. – Rolando

0

Zmagam się z tym zagadnieniem rozsyłającym JAXB XML w formacie wiosna-webmvc dla dni, próbując każdego obejścia, które mogłem zgłębić. Mam teraz zdecydował się użyć Jackson, zastępując Jaxb2RootElementHttpMessageConverter z MappingJackson2XmlHttpMessageConverter który działa out-the-box, co następuje:

import java.util.List; 

import org.springframework.context.annotation.Configuration; 
import org.springframework.http.converter.HttpMessageConverter; 
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 

@Configuration 
@EnableWebMvc 
public class RestConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
     converters.add(new MappingJackson2XmlHttpMessageConverter()); 
    } 

} 

nb Zmagałem się, aby uzyskać konfigurację Java, aby odebrać zmianę w HttpMessageConverter, ponieważ miałem również <mvc:annotation-driven/> w kontekście xml Spring'a, który wydawał się nadpisywać konfigurację Java.

6

wystarczy dodać produces = MediaType.APPLICATION_JSON_VALUE do @RequestMapping

+0

To rozwiązanie sprawdziło się u mnie – Maxvader