2013-11-01 6 views
7

Ich habe unsere Projekte (Java EE basierend auf Websphere 8.5) aktualisiert, um eine neue Version eines firmeninternen Frameworks (und Ejb 3.x Deployment Deskriptoren anstelle der 2. x Einsen). Seitdem scheitern meine Integrationstests mit folgender Ausnahme:Setzen Sie die JAXB Kontext Factory Initialisierungsklasse zu verwenden

Ich kann die Anwendung mit der vorherigen Framework-Version erstellen und alles funktioniert gut. Während das Debuggen bemerkte ich, dass innerhalb der ContextFinder (javax.xml.bind) gibt es zwei unterschiedliche Verhaltensweisen:

  1. vorherige Version (Alles funktioniert gut): Keine der verschiedenen Orte bringt eine Factory-Klasse, so dass die nach oben Die Standard-Factory-Klasse wird geladen. Dies ist com.sun.xml.internal.bind.v2.ContextFactory (definiert als String-Konstante innerhalb der Klasse).

  2. Verbesserte Version (ClassNotFound): Es wurde eine Ressource "META-INF/services/javax.xml.bind.JAXBContext" erfolgreich geladen und die erste gelesene Zeile veranlasst den ContextFinder, "com.ibm.xml" zu laden .xlxp2.jaxb.JAXBContextFactory ", wodurch der Fehler verursacht wird.

Ich habe jetzt zwei Fragen:

  1. Was für eine Art ist, dass Ressource? In unserem EAR gibt es zwei WARs, und keines davon enthält einen Verzeichnisdienst in seinem Verzeichnis META-INF.

  2. Wo könnte dieser Wert von sonst sein? Weil ein Angreifer mir keine neuen oder geänderten Eigenschaftendateien gezeigt hat.

Keine Notwendigkeit zu sagen, dass ich alles über die JAXB Konfigurationsmöglichkeiten lesen werde, aber wenn Sie einen ersten Einblick auf das, was schief gegangen sein könnte oder mich mit dieser Ressource helfen (ist es eine echte Datei i haben suchen Sie nach?) ID schätzen eine Menge. Danke vielmals!

EDIT (nach Kommentare Input/Fragen):

Aus Neugier hat Ihr Rahmen umfassen JAXB JARs? Hat die alte Version Ihres Frameworks jaxb.properties enthalten?

Tat (ich bin ein wenig überrascht) der Rahmen hat einen maßgeschneiderten Eclipse-2.4.1-.jar innerhalb der EAR, die sowohl eine JAXB Umsetzung und eine jaxb.properties-Datei enthält, die den folgenden Eintrag in beide zeigen Versionen (die, die das Werk als auch in dem einen findet, der die Ausnahme auslöst):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

ich denke, das ist, haben nichts mit der aktuellen Ausgabe zu tun, da das Glas genau das gleiche in beiden Ohren war (dasjenige, das läuft/das mit der Erwartung)

Es ist mir auch nicht klar, warum die alte Version des Frameworks jemals die com ausgewählt hat.Umsetzung Sonne

Es gibt eine Klasse javax.xml.bind.ContextFinder, die zur Initialisierung des JAXBContextFactory verantwortlich ist. Diese Klasse durchsucht verschiedene Programme nach der Existenz einer jaxb.properties-Datei oder einer javax.xml.bind.JAXBContext-Ressource. Wenn alle diese Orte zeigen Dont auf die Context-Fabrik dort zu verwenden, ist eine deault Fabrik geladen, die in der Klasse fest einprogrammiert selbst:

private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory"; 

Nun zurück zu meinem Problem:

Gebäude mit dem vorherigen Version des Frameworks (und EJB 2.x Deployment Deskriptoren) funktioniert alles gut). Während des Debuggens kann ich sehen, dass keine Konfiguration gefunden wurde und daher die oben genannte Standard-Factory geladen wird.

Erstellen mit der neuen Version des Frameworks (und EJB 3.x Deployment Deskriptoren, so dass ich bereitstellen kann) NUR ein Testfall schlägt fehl, aber der Rest der Funktionalität funktioniert (wie ich Anfragen an unseren Webservice senden kann und sie keine auslösen Fehler). Beim Debuggen kann ich sehen, dass eine Konfiguration gefunden wurde. Diese Ressource heißt "META-INF/services/javax.xml.bind.JAXBContext". Hier sind die wichtigsten Zeilen, wie diese Ressource zu dem Versuch führt, 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory' zu laden, was dann die ClassNotFoundException auslöst. Dies vereinfacht Quelle der javax.xml.bind.ContextFinder Klasse erwähnt:

URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext"); 

BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8")); 

String factoryClassName = r.readLine().trim(); 

Das Feld factoryClassName hat nun den Wert ‚com.ibm.xml.xlxp2.jaxb.JAXBContextFactory‘

Da dies hat werde eine super Lagerfrage ich werde auch eine Prämie hinzufügen :) Ich werde den ganzen Tag daran arbeiten und Sie wissen lassen, ob es Neuigkeiten gibt.

Update/Lösung

Diese Frage ist gelöst. Das ursprüngliche Problem ist aufgetreten, weil eine falsche Konfiguration komplex aufgebauter Modell-Maven-Projekte erstellt wurde, bei denen eine Abhängigkeit eine aktualisierte Version eines angepassten Eclipse-Verknüpfungs-Jars verwendete, das eine Definition für eine JAXBFactory enthielt, die in der Komponente, in der der Fehler auftrat, nicht verfügbar war. Das Festlegen der JAXB-Kontextfactory wird in den meisten Fällen mit einer jaxb.propertio-Datei oder einer JAXBContext-Datei konfiguriert, die dieselbe Definition enthält. Der detaillierte Ladevorgang der entsprechenden JAXBContextFactory erfolgt in javax.xml.bind.ContextFinder.

Der Fehler ist noch nicht gelöst (während der Tatsache über 4 große EE/SE-Anwendungen führen zu dem Fehler) und es gibt keine allgemeine Antwort, aber dass JAXBContextFactorys muss in Ihrem Klassenpfad (wow was für ein Wunder ...) Sie haben also entweder einen ClassNotFound Error, weil Ihnen Ressourcen fehlen (das ist der eigentliche Grund) oder weil Sie eine falsche JAXBContextFactory in einer der oben erwähnten Property-Dateien definiert haben, die eine Definition gemäß der folgenden Antwort enthalten.

Vielen Dank für Ihre tollen Kommentare und Unterstützung, ich schätze wirklich!

+0

Vielen Dank für die Bearbeitung! – JBA

+0

Aus Neugier, umfasst Ihr Framework JAXB JARs? Hat die alte Version Ihres Frameworks jaxb.properties enthalten? Es ist mir nicht klar, wie Sie in einer Situation gelandet sind, in der Ihr Application Class Loader die META-INF/services-Datei, aber nicht die Implementierungsklasse sehen kann. Mir ist auch nicht klar, warum die alte Version des Frameworks jemals die com.sun-Implementierung ausgewählt hat. –

+0

Vielen Dank für Ihre Eingabe, ich bearbeite die Fragen, um hoffentlich weitere Informationen zu geben – JBA

Antwort

5

Sie können eine jaxb.properties-Datei in dasselbe Paket wie Ihr Domänenmodell aufnehmen, um die JAXB-Implementierung (JSR-222) anzugeben, die Sie verwenden möchten. Zum Beispiel würde es wie folgt aussehen, um EclipseLink MOXy als Ihren JAXB-Provider anzugeben.

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

Weitere Informationen

+0

@ user1902288 - Wer stellt den Eintrag "META-INF/services/javax.xml.bind.JAXBContext", Sie oder WebSphere bereit? –

+0

@BlaiseDoughan Es wird von WebSphere bereitgestellt. –

+0

Ich habe Ihre Antwort aktualisiert, da dies der offizielle Weg ist, die gewünschte ContextFactory einzurichten. Auch wenn ich diese Datei in beiden Modellpaketen platziert habe (sowohl im Service als auch in den Integrationstests), tritt der Fehler immer noch auf und ich debugge gerade, warum er diese jaxb.properties nicht findet. Sobald es funktioniert, werde ich Ihre Antwort annehmen, um Ihnen die Reputationsbelohnung zu bringen. Ich denke, das ist der beste Weg, um sicherzustellen, dass das ContextFacory des Orakels jdk genommen wird. – JBA

3

Eine weitere quick and dirty Lösung (eine Abhilfe, wirklich), die für mich gearbeitet ist, um explizit eine JAXB Umsetzung gehören zu der Maven Build. Zum Beispiel

<dependency> 
    <groupId>javax.xml.bind</groupId> 
    <artifactId>jaxb-api</artifactId> 
    <version>2.2.7</version> 
</dependency> 
<dependency> 
    <groupId>com.sun.xml.bind</groupId> 
    <artifactId>jaxb-impl</artifactId> 
    <version>2.2.7</version> 
</dependency> 

Beachten Sie, dass dies eine irgendwie unnötige Abhängigkeit zu Ihren Build fügt, wie JAXB offensichtlich bereits Teil jeder JRE> = Version 6.

Wahrscheinlich dies funktionieren wird nur, wenn der Klassenlader WAS ist Zuletzt auf Eltern festgelegt.

+0

Ich glaube nicht, dass es standardmäßig funktioniert - WAS wird immer noch seine eigene Implementierung vom übergeordneten Klassenlader verwenden. – kboom

+1

Es funktionierte für mich zu der Zeit definitiv. Vielleicht wäre es eine Option, den WAS-Klassenlader auf den übergeordneten Wert zu setzen, oder die Standardimplementierung wie hier beschrieben zu deaktivieren/ändern: http://StackOverflow.com/a/10002848/1845976 oder es funktioniert genauso wie für JAXWS, wie hier beschrieben: http://stackoverflow.com/questions/24864549/error-deploying-jaxws-webservice-on-websphere-server/24866039#24866039 – schnatterer

+0

Sie haben Recht! Dies ist eine gültige Lösung, aber bitte fügen Sie dies in Ihre Antwort ein. – kboom

Verwandte Themen