it-swarm.com.de

javax.xml.bind.JAXBException: Class *** oder eine ihrer Superklassen ist diesem Kontext bekannt

Ich versuche, ein Objekt über den REST - Webdienst zu übergeben. Im Folgenden werden in meinen Klassen die Funktionen erläutert, die ich anhand einiger Beispielcodes benötige. 

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

Antwortklasse

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

Abteilungsklasse

@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 getDepartments-Methode in der Rest-Web-Service-Klasse anrufe, wird sie mit folgenden Ausnahmen zurückgegeben. Wenn ich jedoch den Typ Object der Payload in Department in der Response-Klasse ändere, wird die Json-Antwort korrekt zurückgegeben. Da ich diese Antwortklasse jedoch für verschiedene Klassen verwenden muss, kann ich die Nutzlast nicht auf einen Klassentyp beschränken. Kann mir bitte jemand in dieser Angelegenheit helfen?

Stapelverfolgung  

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
39
Shanaka

JAX-RS-Implementierungen unterstützen automatisch das Marshalling/De-Marshalling von Klassen basierend auf auffindbaren JAXB-Annotationen. Da Ihre Nutzlast jedoch als Object deklariert ist, fehlt der erstellten JAXBContext die Department-Klasse.

Eine schnelle und schmutzige Lösung wäre, Ihrer Antwortklasse eine XmlSeeAlso -Anmerkung hinzuzufügen:

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

oder etwas komplizierter wäre es, den JAXB-Kontext für die Response-Klasse mit einer ContextResolver "anzureichern":

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);
    }
}
57
Bogdan

Ich habe das gleiche Problem und habe es gelöst, indem ich ein Paket zum Erkunden des Jaxb2marshaller hinzugefügt habe. Für den Frühling wird eine Bohne wie folgt definiert:

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

Wenn sich alle Ihre Anforderungs- und Antwortklassen im selben Paket befinden, müssen Sie die Klassen im JAXBcontext nicht ausdrücklich angeben

5
ftrujillo

Diese Ausnahme kann durch Angabe eines vollständigen Klassenpfads behoben werden.

Beispiel:

Wenn Sie eine Klasse mit dem Namen ExceptionDetails verwenden


Falscher Weg, Argumente zu übergeben  

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

Richtiger Weg der Argumentation

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

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 funktioniert (was darauf hindeutet, dass das Problem möglicherweise der Klassenlader in JBoss ist). 

Dies ist der Code, der den Fehler ausgegeben hat (d. H. 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, der funktioniert hat (ValueSet ist eine der Klassen, die aus meinem XML-Marshall erstellt wurden). 

private static final JAXBContext JC;

static {
    try {
        ClassLoader classLoader = ValueSet.class.getClassLoader();
        JC = JAXBContext.newInstance("org.foo.bar", classLoader);
    } catch (Exception exp) {
        throw new RuntimeException(exp);
    }
}

In einigen Fällen habe ich die Klasse noch in diesem Zusammenhang kennen gelernt. In anderen Fällen bekam ich auch eine Ausnahme von org.foo.bar.ValueSet kann nicht in org.foo.bar.ValueSet umgewandelt werden (ähnlich dem hier beschriebenen Problem: ClassCastException beim Umwandeln in dieselbe Klasse ). 

1
John

Bei der Unterstützung einer Anwendung hatte ich einen ähnlichen Fehler. Es ging um die generierten Klassen für einen SOAP Webservice.

Das Problem wurde aufgrund der fehlenden Klassen verursacht. Als javax.xml.bind.Marshaller versuchte, das jaxb-Objekt zu marshallen, wurden nicht alle abhängigen Klassen gefunden, nach denen von wsdl und xsd generiert wurde. Nachdem das Glas mit allen Klassen im Klassenpfad hinzugefügt wurde, wurde das Problem behoben.

1
Sandesh Dhotre

Ich weiß, dass es eine alte Frage ist, aber Sie können die Antwort mit einem Parameter (P) ändern:

public class Response<P> implements Serializable{

private static final long serialVersionUID = 1L;

public enum MessageCode {
    SUCCESS, ERROR, UNKNOWN
}

private MessageCode code;
private String message;
private P payload;

...
public P getPayload() {
    return payload;
}

public void setPayload(P payload) {
    this.payload = payload;
}

}

Die Methode wäre

public Response<Departments> getDepartments(){...}

Ich kann es jetzt nicht probieren, aber es sollte funktionieren.

Ansonsten ist es möglich, Response zu erweitern

@XmlRootElement    
public class DepResponse extends Response<Department> {<no content>}
0
Daniele Licitra

Ftrujillos Antwort funktioniert gut, aber wenn Sie nur ein Paket zum Scannen haben, ist dies die kürzeste Form:

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("your.package.to.scan");
        return marshaller;
    }
0

Dieser Fehler tritt auf, wenn wir denselben Methodennamen für Jaxb2Marshaller verwenden, zum Beispiel:

    @Bean
    public Jaxb2Marshaller marshallerClient() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // this package must match the package in the <generatePackage> specified in
        // pom.xml
        marshaller.setContextPath("library.io.github.walterwhites.loans");

        return marshaller;
    }

Und in einer anderen Datei

    @Bean
    public Jaxb2Marshaller marshallerClient() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        // this package must match the package in the <generatePackage> specified in
        // pom.xml
        marshaller.setContextPath("library.io.github.walterwhites.client");

        return marshaller;
    }

Auch wenn es eine andere Klasse ist, sollten Sie sie anders benennen

0
Walterwhites