2012-12-27 6 views
26

Ich versuche, ein Objekt über REST-Webdienst zu übergeben. Im Folgenden sind meine Klassen erklärt die Funktionalität, die ich mit einigen Beispielcodes benötigen.javax.xml.bind.JAXBException: Klasse *** noch eine Superklasse ist in diesem Kontext bekannt

Erholung Web Service Class Methode

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

Abteilung Klasse

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

} 

Wenn ich die Methode getDepartments in der restlichen Web-Service-Klasse anrufe, werden folgende Ausnahmen zurückgegeben. Aber wenn ich den Typ Objekt der Nutzlast zu Abteilung in der Antwortklasse ändern, gibt es die JSON-Antwort korrekt zurück. Aber da ich diese Antwortklasse für verschiedene Arten von Klassen verwenden muss, kann ich die Nutzlast nicht auf einen Klassentyp umlenken. Kann mir bitte jemand in dieser Angelegenheit helfen?

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 
+5

Sie sollten die bereitgestellte Antwort akzeptieren, da es gut funktioniert. – Daniel

+0

@Shanaka akzeptieren eine der bereitgestellten Antworten, #Bogdan Antwort ist ziemlich gut. Wähle eine beste Antwort und hilf anderen, weise zu wählen – Jeevanantham

Antwort

49

JAX-RS-Implementierungen automatisch Rangier-/unmarshalling von Klassen basierend auf Erkennbar JAXB Annotationen unterstützen, sondern weil Ihre Nutzlast als Object deklariert wird, denke ich, die erstellt JAXBContext verfehlt die Department Klasse und wenn es Zeit ist, es zu marshall es weiß nicht wie.

A quick and dirty fix wäre eine XmlSeeAlso Anmerkung zu Ihrer Antwort Klasse hinzuzufügen:

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

oder etwas ein wenig komplizierter wäre, der JAXB Kontext für die Response Klasse „zu bereichern“, indem ein mit :

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); 
    } 
} 
+1

Ich habe eine Liste von Objekten innerhalb von Objekten. Gelöst durch das '@ XmlSeeAlso'-Tag. Danken! – Daniel

+1

funktioniert nicht für mich :( – Anas

+0

Wenn ich XmlSeeAlso Annotation verwendet, fügen Sie diese Informationen zum Knoten: xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: type = "meine_klasse" gibt es Möglichkeit, das entfernen? –

5

Diese Ausnahme kann durch Angabe des vollständigen Klassenpfads gelöst werden.

Beispiel:

, wenn Sie Klasse als ExceptionDetails benannt sind.java


Wrong Way des Führens Argumente

JAXBContext jaxbContext = JAXBContext.newInstance(ExceptionDetails.class); 

richtige Weg des Führens Argumente

JAXBContext jaxbContext = JAXBContext.newInstance(com.tibco.schemas.exception.ExceptionDetails.class); 

Vielen Dank, Partha

+7

Sicherlich das Paket Angabe nur einen Unterschied machen würde, wenn Sie in verschiedenen Paketen und die Import-Anweisung wurde mit der „anderen“ eins zwei verschiedene Versionen von ExceptionDetails hatte ? – DarthPablo

2

Ich habe das gleiche Problem, und ich löste es durch Paket zum Jaxb2marshaller zu erkunden hinzufügen. Für das Frühjahr eine Bohne wie folgt definieren wird:

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

Auf diese Weise, wenn alle Ihre Anfrage und Antwort Klassen im selben Paket sind Sie brauchen, um anzuzeigen, nicht speziell die Klassen auf der JAXBcontext

0

Ich hatte Ein ähnliches Problem mit der JAXB-Referenzimplementierung und JBoss AS 7.1. Ich konnte einen Integrationstest schreiben, der bestätigte, dass JAXB außerhalb der JBoss-Umgebung arbeitete (was darauf hindeutet, dass das Problem möglicherweise der Klassenlader in JBoss ist).

Dies ist der Code, der den Fehler gab (das heißt nicht funktioniert):

private static final JAXBContext JC; 

static { 
    try { 
     JC = JAXBContext.newInstance("org.foo.bar"); 
    } catch (Exception exp) { 
     throw new RuntimeException(exp); 
    } 
} 

und dies ist der Code, arbeitete (ValueSet ist eine der Klassen von meinem XML serialisiert).

In einigen Fällen habe ich die Klasse noch irgendeine ihrer Superklasse ist in diesem Zusammenhang bekannt. In anderen Fällen habe ich auch eine Ausnahme von org.foo.bar.ValueSet kann nicht in org.foo.bar.ValueSet (ähnlich dem hier beschriebenen Problem: ClassCastException when casting to the same class) umgewandelt werden.

Verwandte Themen