Remote-Web-Client: ClassNotFoundException

schnuffie

Erfahrenes Mitglied
Hallo Experten,

die Anwendung läuft auf einem JBoss. Mittels Web-Applikation auf einem Tomcat wird auf die JBoss-Anwendung remote zugegriffen.
Solange ich nichts aus dem CommonsJAR lade, funktionierts, d.h. die Remote-Beans werden anstandslos geladen, wenn deren Methoden nichts aus dem CommonsJAR benutzen. Sonst kommt:
Code:
...
Caused by: java.lang.ClassNotFoundException: [Klasse aus dem CommonsJAR]
 at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
 at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:247)
 at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
 at org.jboss.invocation.MarshalledValueInputStream.resolveClass(MarshalledValueInputStream.java:109)
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
 at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
 at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1624)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
 at org.jboss.invocation.MarshalledValue.get(MarshalledValue.java:91)
 at org.jboss.invocation.unified.interfaces.UnifiedInvokerProxy.invoke(UnifiedInvokerProxy.java:196)
 at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerInterceptor.java:365)
 at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:197)
 at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:61)
 at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:70)
 at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:112)
 at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:100)
Wie der Fehlermeldung zu entnehmen ist, kommt der Fehler vom JBoss.

Remote-Loader:
Code:
privatestatic Object lookupHome(java.util.Hashtable environment, String jndiName, Class narrowTo) throws javax.naming.NamingException {
// Obtain initial context
Context initialContext = new javax.naming.InitialContext(environment);
try {
Object objRef = initialContext.lookup(jndiName);
// only narrow if necessary
if (java.rmi.Remote.class.isAssignableFrom(narrowTo))
return javax.rmi.PortableRemoteObject.narrow(objRef, narrowTo);
else
return objRef;
} finally {
initialContext.close();
}
}

jboss-app.xml:
HTML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd">
<jboss-app>
 <loader-repository>
  [Package]:loader=[Name ROOT-Folder s.u.]
  <loader-repository-config>
   java2ParentDelegation=false
  </loader-repository-config>
 </loader-repository>
</jboss-app>

JBoss 4.2.3 - offen deploytes EAR:
HTML:
ROOT-Folder
-JAR mit EJB2-Bean
ROOT-Folder/lib
-JAR mit EJB2-Remote-Interface und Home
-CommonsJAR

Tomcat - offen deploytes WAR:
HTML:
ROOT-Folder/WEB-INF/lib
-JAR dieses Web-Clients
-JAR mit EJB2-Remote-Interface und Home
-CommonsJAR

Woran könnte das liegen?
 
Hallo,

ich gehe mal davon aus, dass Du eine J2EE 1.4 kompatible Anwendung hast (wegen der Erwähnung von EJB 2). Prinzipiell gibt es das implizite Laden von jar's aus dem lib Verzeichniss einer ear aber erst ab JEE 5.

Da du einen eigenen Loader definierst, schau doch einfach mal in der jmx-console das entsprechende MBean an - dort findest Du eine Übersicht über alle URL's des Loaders. Wenn Dein jar nicht darin auftaucht, kann er nicht darauf zugreifen. Alternativ kannst Du auch mal die displayClassInfo() MBean Operation auf dem Loader ausführen (ganz unten) und ihr den gesuchten Klassennamen geben - wenn er die Klasse findet, sollte eine entsprechende Meldung (### Instance found in UCL: .... ) kommen.

Die Standardvariante um in J2EE 1.4 andere jars von Bibliotheken etc. einzubinden geht über die MANIFEST.MF Datei des jeweiligen Moduls (also z.B. deiner ejb.jar). Dort trägst Du das entsprechende jar in den Classpath ein, also ungefähr so.
Code:
Class Path: lib/commons.jar
Jetzt sollte er es auch laden.

hth
THMD
 
Hi THMD,

ja, JSEE1.4 ist es.

Der Loader zeigt die JARs an, auch das CommonJAR ist dabei:
HTML:
file:/D:/Projekte/jboss-4.2.3/server/default/deploy/[EAR-ROOT-Folder]/lib/common.jar

Das Ausführen Deiner benannten Funktion findet die Klasse:
HTML:
Not loaded in repository cache


### Instance0 found in UCL: org.jboss.mx.loading.UnifiedClassLoader3@10dbef1{ url=file:/D:/Projekte/jboss-4.2.3/server/default/deploy/[EAR-ROOT-Folder]/ ,addedOrder=44}

Danke für die Tipps, ich werd' nun mal die Classenpfade zwischen den JARs prüfen und ggf. anpassen.
 
Inzwischen hatte ich vermutet, es könne daran liegen, daß meine Anwendungs-JARs verteilt lagen, d.h. alle in der application.xml aufgelisteten EJB- oder WAR-Files lagen im Root und alle anderen JARs im Unterordner "lib".

Geladen wurden alle Klassen lt. JBoss-Console, jedoch deployed der JBoss alles nach /tmp/deploy OHNE Unterordner "lib". Damit sind meine Classpath-Angaben in den JARs hinfällig.

Nun habe ich aber inzwischen ALLE Anwendungs-JARs ins Root deployed, die Referenzen in den JARs entsprechend angepaßt und bekomme aber immernoch den gleichen Fehler!

Code:
java.lang.reflect.UndeclaredThrowableException
 at $Proxy5.doNachForschung4Internet(Unknown Source)
 at internet.proxies.MgrProxy.doNachForschung4Internet(MgrProxy.java:337)
 at de.dbsystems.vug.internet.VuGInternetManager.doNachforschung(InternetManager.java:873)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:129)
 at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63)
 at javax.faces.component.UICommand.broadcast(UICommand.java:106)
 at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:94)
 at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:168)
 at org.apache.myfaces.lifecycle.LifecycleImpl.invokeApplication(LifecycleImpl.java:343)
 at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:86)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:137)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at de.dbsystems.vug.internet.filter.VuGPerfLogRequestFilter.doFilter(VuGPerfLogRequestFilter.java:72)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at de.dbsystems.vug.internet.filter.SecurityFilter.doFilter(SecurityFilter.java:95)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
 at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassNotFoundException: model.ViewDetails at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
 at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:247)
 at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
 at org.jboss.invocation.MarshalledValueInputStream.resolveClass(MarshalledValueInputStream.java:109)
 at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
 at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
 at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1624)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
 at org.jboss.invocation.MarshalledValue.get(MarshalledValue.java:91)
 at org.jboss.invocation.unified.interfaces.UnifiedInvokerProxy.invoke(UnifiedInvokerProxy.java:196)
 at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerInterceptor.java:365)
 at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:197)
 at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:61)
 at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:70)
 at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:112)
 at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:100)
 ... 33 more

Signatur der Methode:
Code:
public ViewDetails[] doNachForschung4Internet(String code, String sprache)
throws EJBException, AppException {
// ...
ViewDetails[] viewDetails = new ViewDetails[datas.length];
// ...
return viewDetails;
}
 
Hallo,

das Verhalten ist schon ein bischen komisch. Wie gesagt, wenn das Loaderrepository das jar entsprechend in seinen URL's anzeigt und die Suche nach der Klasse ein Ergebnis bringt, sollte auch die Anwendung für die das Repository definiert ist, in der Lage sein die Klasse zu laden.

Das einzige was mir spontan noch einfällt, wäre der Versuch die common.jar als Client jar in der application.xml einzutragen.
Code:
<module>
     <java>common.jar</java>
</module>
Ist dann zwar nicht die sauberste Lösung, aber vielleicht hilft es ja.

Gruß
THMD
 
Vielen Dank, THMD, nach reichlicher Verzweiflung habe ich die Lösung gefunden. Ganz schön fies die Sache! :mad:

Als Erstes, die geworfene Exception ist nicht die, die im Stack-Trace erscheint, denn eigentlich fliegt diese:
Code:
Caused by: java.lang.ClassNotFoundException: [Lmodel.ViewDetails;
Sieht genauso aus? Auf den ersten Blick vielleicht, doch "[L" zu Beginn weißt auf einen Array hin - sieht man ja auch in meiner Methodensignatur. Dieser URLClassLoader verschluckt das einfach und gibt nur den Namen der Klasse zurück (siehe Stacktrace meines letzten Posts). Nachdem ich das herausgefunden und zahlreiche Webseiten durchwühlt hatte, bin ich auf einen interessanten Post gestoßen:
http://javathreads.de/2008/06/bug-oder-feature-in-java-6/ :)

Dort steht zu dem Problem Folgendes:
HTML:
Der interessante Teil an der Exception ist "Caused by: java.lang.ClassNotFoundException: [Ljava.lang.String;", welcher nicht erklärbar scheint.
Die Lösung bzw. Workaround dafür schon einmal vorab. Der JRE 6 bzw JDK 6 als VM Argument folgendes mitgeben: -Dsun.lang.ClassLoader.allowArraySyntax=true
Ist dieses Argument gesetzt tritt die Exception nicht mehr auf.
In einem Forum habe ich dann den Hinweis auf einen Bug Report bei Sun gefunden der dieses Verhalten beschreibt und folgendes Beispiel zum reproduzieren des Bugs auflistet:
view plaincopy to clipboardprint?
public class test { 
public static void main(String[] args) throws Exception { 
String[] s = new String[] { "123" }; 
String clName = s.getClass().getName(); 
test.class.getClassLoader().loadClass(clName); 
} 
} 
public class test {
public static void main(String[] args) throws Exception {
String[] s = new String[] { "123" };
String clName = s.getClass().getName();
test.class.getClassLoader().loadClass(clName);
}
}
Mit Java 5 (1.5) läuft dieser Code wunderbar aber mit Java 6.0 erhält man eben diese ominöse ClassNotFoundException Exception

Nachdem ich meiner JVM den Parameter "-Dsun.lang.ClassLoader.allowArraySyntax=true" mitgegeben habe, läuft's! :)
 

Neue Beiträge

Zurück