Search the FirstSpirit Knowledge Base
Hallo Zusammen,
Ich denke ich habe ein Problem mit dem Classloader.
Konkret habe ich eine ProjectApp geschrieben, die einige 3rd-Party-Jars mitbringt.
Die ProjectApp bringt eine Klasse mit, die den Programmablauf enthält und aus einem Beanshell-Skript im SiteArchitect aufgerufen wird.
In der App sollen aus einem bestehenden System Dokumente gelesene werden und anschließend ins FirstSpirit importiert werden.
Dazu wird irgendwann im Programmablauf in einer der 3rd-Party-Jars ein XML-Parser gebraucht.
ERROR: 'Das erste Argument für die nicht-"static"-Java-Funktion "externalURL" ist keine gültige Objektreferenz.'
FATAL ERROR: 'Das erste Argument für die nicht-"static"-Java-Funktion "externalURL" ist keine gültige Objektreferenz.'
javax.xml.transform.TransformerConfigurationException: Das erste Argument für die nicht-"static"-Java-Funktion "externalURL" ist keine gültige Objektreferenz.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Unknown Source)
...
...
Eigentlich sollte an dieser Stelle ein eigene TransformerFactory genutzt werden.
Diese liegt in einem der Jars und sollte für den FactoryFinder durch einen Eintrag im META-INF-Verzeichnis des Jars("META-INF/services/javax.xml.transform.TransformerFactory") zu finden sein.
Auszug aus der Standard-Java-Klasse javax.xml.transform.TransformerFactory:
public static TransformerFactory newInstance()
throws TransformerFactoryConfigurationError {
try {
return (TransformerFactory) FactoryFinder.find(
/* The default property name according to the JAXP spec */
"javax.xml.transform.TransformerFactory",
/* The fallback implementation class name, XSLTC */
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
} catch (FactoryFinder.ConfigurationError e) {
throw new TransformerFactoryConfigurationError(
e.getException(),
e.getMessage());
}
}
Wie es ausschaut greift hier der Fallback.
Versuche ich die Klasse direkt in meiner ProjectApp aufzurufen:
Class.forName("paket.klassenname");
ist diese auch zu finden.
Setze ich anschließend ein entsprechendes System.property
System.setProperty("javax.xml.transform.TransformerFactory", "paket.klassenname");
erhalte ich im nach folgenden Programmablauf eine ClassNotFoundException an entsprechender Stelle:
java.lang.ClassNotFoundException: paket.klassenname
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at javax.xml.transform.FactoryFinder.getProviderClass(Unknown Source)
at javax.xml.transform.FactoryFinder.newInstance(Unknown Source)
at javax.xml.transform.FactoryFinder.find(Unknown Source)
... 35 more
Anscheinend habe ich hier ein kleines ClassLoader-Problem bei dem ich mir leider nicht zu helfen weiß.
Die ganzen Jars habe ich schon auf verschiedene Weisen versucht über die module.xml einzubinden.
Entweder waren diese als Library-Komponene oder direkt in der ProjektApp mit server-Scope angegeben.
In beiden Fällen habe ich versucht einmal diese ganzen 3rd-Party-Jars einzeln oder zusammen in einer großen Jar-Datei zu laden.
Allerdings konnte ich keine Unterschiede bei der Ausführugn feststellen.
Kann mir jemand einen Hinweis geben warum die gesucht Klasse zwar im Modul, aber nicht über den System(?)-ClassLoader zu finden ist?
Viele Grüße
Stephan
Hallo,
um welche FS Version handelt es sich hier?
Kannst du bitte deine module.xml mal hier posten.
Gruß
Thorsten
Hallo,
konntest du dein Problem inzwischen selbst lösen? Dann wäre es gut, wenn du die Lösung hier kurz erläutern würdest. Falls du weiterhin Unterstützung benötigst, solltest du Thorstens Fragen beantworten.
Viele Grüße
Tim
Ich bin gerade über diesen Forenbeitrag gestolpert, weil ich ein ähnliches Problem hatte. Wir haben ein Modul das eine Public-Klasse enthält, über die per Skript ein Import-Auftrag gestartet wird.
Ich habe auch einige 3rd-Party Libraries zum XML Parsen verwendet und festgestellt, dass keine Klassen über javax.xml.parsers.FactoryFinder instanziiert werden können.
Es sieht so aus als könnte die Klasse FactoryFinder keine Resourcen aus dem Modul finden. Ich habe dann festgestellt, dass die Klasse FactoryFinder den Classloader aus dem Thread verwendet. Als Lösung habe den Classloader im Thread überschrieben. Ich weiß nicht ob das eine empfehlenswerte Lösung ist aber bei mir hat es das Problem gelöst.
ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
try {
//execute your code
} catch (Exception e) {
//Log exception here
} finally {
Thread.currentThread().setContextClassLoader(originClassLoader);
}