2017-09-05 1 views
0

Ich erstelle eine Rest-API, die ein XML-Dokument konsumieren und zwei Objekte aus diesem Dokument erstellen wird. Die Objekte werden dann in einer Datenbank mit Hibernate gespeichert. Dies ist, was ich gerade habe:Erzeuge zwei Objekte aus einem XML-Dokument mit Jaxb

@PUT 
@Path("saveVehicle") 
@Consumes("application/xml;charset=utf-8") 
@Produces("text/plain") 
public String saveVehicleData(String xml) { 
    DBClient client = new DBClient(); 
    Session session = client.getVehicleSession(); 
    JAXBContext jaxbContext; 

    try { 
     Reader reader = new StringReader(xml); 
     XMLInputFactory factory = XMLInputFactory.newInstance(); 
     XMLStreamReader xmlReader = factory.createXMLStreamReader(reader); 

     jaxbContext = JAXBContext.newInstance(VehicleData.class); 
     Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
     VehicleData vehicle = (VehicleData) jaxbUnmarshaller.unmarshal(xmlReader); 

     session.saveOrUpdate(vehicle); 
     session.flush(); 

     jaxbContext = JAXBContext.newInstance(VehicleOwner.class); 
     jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
     VehicleOwner owner = (VehicleOwner) jaxbUnmarshaller.unmarshal(xmlReader); 

     session.saveOrUpdate(owner); 
     session.flush(); 

     return vehicle.getRegistrationNo() + " " + owner.getName(); 
    } catch (JAXBException e) { 
     e.printStackTrace(); 
     return "JAXBException " + e.getMessage() + "\nCaused by " + e.getCause(); 
    } catch (XMLStreamException e) { 
     e.printStackTrace(); 
     return "XMLStreamException " + e.getMessage(); 
    } 
} 

Wie Sie sehen können, soll diese Methode XML als Zeichenfolge aufnehmen. Aus diesem Dokument generiert es dann ein Fahrzeug und einen Fahrzeugbesitzer. Das Dokument enthält Informationen über Fahrzeuge und ihre Besitzer, aber ich möchte sie in separaten Datenbanktabellen. Die Klassen verwenden Jaxb-Annotationen für alle Felder, die in der Datenbank gespeichert werden sollen. jedoch Wenn ich versuche, dies zu laufen, ich folgendes stacktrace erhalten:

java.lang.ClassCastException: org.package.VehicleOwner cannot be cast to org.package.VehicleData 
org.package.rest.LoginController.saveVehicleData(LoginController.java:369) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:498) 
com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) 
com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185) 
com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) 
com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302) 
com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) 
com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) 
com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) 
com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) 
com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1542) 
com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1473) 
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419) 
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409) 
com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409) 
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558) 
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 

Bevor ich das Mapping für Fahrzeugbesitzer hinzugefügt, konnte ich ein VehicleData und speichern sie in der Datenbank instanziieren. Aber jetzt scheint es zu erwarten, dass dieses XML-Dokument einem VehicleOwner zugeordnet wird. Ich dachte, es wäre möglich, das Dokument verschiedenen Klassen zuzuordnen. Ist das nicht der Fall? wenn es ist, wie würde ich es tun?

Antwort

0

Es ist möglich, Dokumente verschiedenen Klassen zuzuordnen, aber anscheinend tun Sie das nicht. Nur tun:

jaxbContext = JAXBContext.newInstance(VehicleData.class); 
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
    VehicleData vehicle = (VehicleData) jaxbUnmarshaller.unmarshal(xmlReader); 

ist kein Wunder Sie XML-Struktur VehicleData Struktur abzubilden. Sie müssen Zuordnungen definieren oder generieren, sodass dieselbe XML verschiedenen Strukturen (/VehicleOwner) in verschiedenen JAXB-Kontexten zugeordnet wird. Sie müssen auch sicherstellen, dass diese Kontexte nicht überschneiden (ich denke, sie tun in Ihrem Fall).

+0

Ich bemerkte, dass ich den gleichen Kontext für beide Klassen verwendet habe, also habe ich das behoben und den Code in der Frage aktualisiert. Allerdings bekomme ich immer noch den gleichen Fehler. Ich glaube nicht, dass ich deine Antwort wirklich verstehe. Dies ist das erste Mal, dass ich versuche, jaxb zu benutzen, also vergib mir, wenn ich etwas Offensichtliches vermisse. Kannst du weiter erklären, was du meinst, wenn du sagst: "Du musst Zuordnungen definieren oder generieren, damit dasselbe XML auf verschiedene Strukturen abgebildet wird" und was bedeutet es, wenn sich Kontexte schneiden? –