Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context

I'm trying to pass a object via REST web service. Following are my classes explains the functionality that I need using some example codes.

Rest Web Service Class method

@POST @Path("/find") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces({MediaType.APPLICATION_JSON}) public Response getDepartments(){     Response response = new Response();      try {          response.setCode(MessageCode.SUCCESS);         response.setMessage("Department Names");         Department dept = new Department("12", "Financial");         response.setPayload(dept);      } catch (Exception e) {         response.setCode(MessageCode.ERROR);         response.setMessage(e.getMessage());         e.printStackTrace();     }            return response; } 

Response Class

import java.io.Serializable; import javax.xml.bind.annotation.XmlRootElement;  @XmlRootElement  public class Response implements Serializable{      private static final long serialVersionUID = 1L;      public enum MessageCode {         SUCCESS, ERROR, UNKNOWN     }      private MessageCode code;     private String message;     private Object payload;      public MessageCode getCode() {         return code;     }      public void setCode(MessageCode code) {         this.code = code;     }      public String getMessage() {         return message;     }      public void setMessage(String message) {         this.message = message;     }      public Object getPayload() {         return payload;     }      public void setPayload(Object payload) {         this.payload = payload;     } } 

Department Class

@XmlRootElement public class Department implements java.io.Serializable {       private String deptNo;     private String deptName;       public Department() {     }      public Department(String deptNo, String deptName) {         this.deptNo = deptNo;         this.deptName = deptName;     }      public String getDeptNo() {         return this.deptNo;     }      public void setDeptNo(String deptNo) {         this.deptNo = deptNo;     }      public String getDeptName() {         return this.deptName;     }      public void setDeptName(String deptName) {         this.deptName = deptName;     }  } 

When I make a call to getDepartments method in the rest web service class it returns following exceptions. But If I change the type Object of the payload to Department in the Response class it returns the json response correctly. But since I need to use this Response class for different types of Classes I can't restring the payload to one class type. Can anyone please help me in this matter?

Stack Trace

Dec 27, 2012 9:34:18 PM com.sun.jersey.spi.container.ContainerResponse logException SEVERE: Mapped exception to response: 500 (Internal Server Error) javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException  - with linked exception: [javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.]     at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:159)     at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)     at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1437)     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)     at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)     at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)     at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)     at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401)     at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)     at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)     at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)     at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)     at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)     at org.mortbay.jetty.Server.handle(Server.java:326)     at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)     at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945)     at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)     at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)     at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)     at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)     at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) Caused by: javax.xml.bind.MarshalException  - with linked exception: [javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.]     at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)     at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:177)     at com.sun.jersey.json.impl.BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:103)     at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:136)     at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:157)     ... 23 more Caused by: javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.     at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:250)     at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:265)     at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:657)     at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156)     at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)     at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:597)     at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:328)     at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:498)     at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:320)     ... 27 more Caused by: javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.     at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:611)     at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:652)     ... 33 more 
like image 918
Shanaka Avatar asked Dec 27 '12 16:12

Shanaka


People also ask

What is javax XML bind MarshalException?

A javax.xml.bind.MarshalException error may occur when a null object is used as an argument to a java.util.List parameter on a JAX-WS web method.

What is JAXB context?

The JAXBContext class provides the client's entry point to the JAXB API. It provides an abstraction for managing the XML/Java binding information necessary to implement the JAXB binding framework operations: unmarshal, marshal and validate.

What is @XmlRootElement?

When a top level class or an enum type is annotated with the @XmlRootElement annotation, then its value is represented as XML element in an XML document. This annotation can be used with the following annotations: XmlType , XmlEnum , XmlAccessorType , XmlAccessorOrder .


2 Answers

JAX-RS implementations automatically support marshalling/unmarshalling of classes based on discoverable JAXB annotations, but because your payload is declared as Object, I think the created JAXBContext misses the Department class and when it's time to marshall it it doesn't know how.

A quick and dirty fix would be to add a XmlSeeAlso annotation to your response class:

@XmlRootElement @XmlSeeAlso({Department.class}) public class Response implements Serializable {   .... 

or something a little more complicated would be "to enrich" the JAXB context for the Response class by using a ContextResolver:

import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException;  @Provider @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public class ResponseResolver implements ContextResolver<JAXBContext> {     private JAXBContext ctx;      public ResponseResolver() {         try {             this.ctx = JAXBContext.newInstance(                          Response.class,                          Department.class                      );         } catch (JAXBException ex) {             throw new RuntimeException(ex);         }     }      public JAXBContext getContext(Class<?> type) {         return (type.equals(Response.class) ? ctx : null);     } } 
like image 54
Bogdan Avatar answered Sep 19 '22 00:09

Bogdan


I have the same problem and I solved it by adding package to explore to the Jaxb2marshaller. For spring will be define a bean like this:

@Bean     public Jaxb2Marshaller marshaller() {         Jaxb2Marshaller marshaller = new Jaxb2Marshaller();         String[] packagesToScan= {"<packcge which contain the department class>"};         marshaller.setPackagesToScan(packagesToScan);         return marshaller;     } 

By this way if all your request and response classes are in the same package you do not need to specifically indicate the classes on the JAXBcontext

like image 28
ftrujillo Avatar answered Sep 19 '22 00:09

ftrujillo