Bugs item #823636, was opened at 2003-10-14 19:20
Message generated for change (Comment added) made by adrianprice
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=376685&aid=823636&group_id=22866

Category: None
Group: v3.2
Status: Open
Resolution: None
Priority: 5
Submitted By: Adrian Price (adrianprice)
Assigned to: Nobody/Anonymous (nobody)
Summary: EAR ClassLoader ignores library jar Class-Path

Initial Comment:
JBoss-3.2.1, j2sdk1.4.0_01, WinXP or Red Hat Linux 9.0.

The JBoss EAR ClassLoader does not appear to honour 
the manifest Class-Path entries in either ejb-jar files 
(declared as <ejb> modules in application.xml) or regular 
library files contained within the EAR archive (packaged 
as peers to ejb-jar files).

According to the J2EE specification and the JBoss 
documentation the arrangement below should work 
correctly, but it doesn't.  By experiment I have 
determined that declaring lib1.jar and lib2.jar as <java> 
modules in application.xml solves the problem, but this is 
clearly not the correct approach (java modules are 
explicitly for client code).

Attached is the following test case that illustrates the 
problem:

my-app.ear
    META-INF/application.xml
    my-ejb.jar
        META-INF/MANIFEST.MF Class-Path: lib1.jar
        tld/domain/MyEJB.class
        tld/domain/MyEJBRemote.class
        tld/domain/MyEJBRemoteHome.class
    lib1.jar
        META-INF/MANIFEST.MF Class-Path: lib2.jar
        tld/domain/A.class
    lib2.jar
        tld/domain/B.class

my-client.jar
    META-INF/MANIFEST.MF Main-Class: 
tld.domain.MyClient
    tld/domain/MyClient.class

Executing the run.cmd script launches MyClient, which 
attempts to create an instance of the MyEJB bean.  The 
server throws the following exception:

17:57:09,089 ERROR [LogInterceptor] Unexpected Error:
java.lang.NoClassDefFoundError: tld/domain/A
        at tld.domain.MyEJB.<clinit>(MyEJB.java:12)
        at 
sun.reflect.NativeConstructorAccessorImpl.newInstance0
(Native Method)
        at 
sun.reflect.NativeConstructorAccessorImpl.newInstance
(NativeConstructorAccessorImpl.java:39)
        at 
sun.reflect.DelegatingConstructorAccessorImpl.newInsta
nce(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance
(Constructor.java:274)
        at java.lang.Class.newInstance0(Class.java:296)
        at java.lang.Class.newInstance(Class.java:249)
        at 
org.jboss.ejb.Container.createBeanClassInstance
(Container.java:469)
        at org.jboss.ejb.plugins.AbstractInstancePool.get
(AbstractInstancePool.java:146)
        at 
org.jboss.ejb.plugins.StatelessSessionInstanceIntercepto
r.invoke(StatelessSessionInstanceInterceptor.java:58)
        at 
org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext
(AbstractTxInterceptor.java:84)
        at 
org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransacti
ons(TxInterceptorCMT.java:243)
        at org.jboss.ejb.plugins.TxInterceptorCMT.invoke
(TxInterceptorCMT.java:104)
        at org.jboss.ejb.plugins.SecurityInterceptor.invoke
(SecurityInterceptor.java:117)
        at org.jboss.ejb.plugins.LogInterceptor.invoke
(LogInterceptor.java:191)
        at 
org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invok
e(ProxyFactoryFinderInterceptor.java:122)
        at 
org.jboss.ejb.StatelessSessionContainer.internalInvoke
(StatelessSessionContainer.java:322)
        at org.jboss.ejb.Container.invoke
(Container.java:674)
        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:324)
        at 
org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke
(ReflectedMBeanDispatcher.java:284)
        at org.jboss.mx.server.MBeanServerImpl.invoke
(MBeanServerImpl.java:549)
        at 
org.jboss.invocation.jrmp.server.JRMPInvoker.invoke
(JRMPInvoker.java:359)
        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:324)
        at sun.rmi.server.UnicastServerRef.dispatch
(UnicastServerRef.java:261)
        at sun.rmi.transport.Transport$1.run
(Transport.java:148)
        at java.security.AccessController.doPrivileged
(Native Method)
        at sun.rmi.transport.Transport.serviceCall
(Transport.java:144)
        at 
sun.rmi.transport.tcp.TCPTransport.handleMessages
(TCPTransport.java:460)
        at 
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.r
un(TCPTransport.java:701)
        at java.lang.Thread.run(Thread.java:536)

----------------------------------------------------------------------

>Comment By: Adrian Price (adrianprice)
Date: 2003-10-15 09:46

Message:
Logged In: YES 
user_id=580837

Many thanks for the response.  However, I beg to differ: the 
J2EE spec. does require recursive resolution of bundled jar file 
Class-Path entries, as does the jar file specification.

"J2EE.8.2.1 Assembling a J2EE Application", j2ee-1_3-fr-
spec.pdf, page 106:

"d. Make sure that each component in the application 
properly describes any dependencies it may have on other 
components in the application. A J2EE application should not 
assume that all components in the application will be available 
on the �classpath� of the application at run time. Each 
component might be loaded into a separate class loader with 
a separate namespace. If the classes in a JAR file depend on 
classes in another JAR file, the first JAR file should reference 
the second JAR file using the Class-Path mechanism. A 
notable exception to this rule is JAR files located in the WEB-
INF/lib directory of a web application. All such JAR files are 
included in the class path of the web application at runtime;
explicit references to them using the Class-Path mechanism 
are not needed."

Recursive Class-Path resolution is the only approach that 
makes sense.  Unless dependencies are declared locally by 
Class-Path attributes in the jar files containing the 
referencing classes and resolved recursively, all such 
dependencies would have to be understood and surfaced by 
top-level ejb-jar files.

This problem is newly introduced between JBoss-3.0.4 and 
3.2.1.  My application runs perfectly on the older version, and 
on other app. servers.

HOWEVER, I must have been tired last night and accidentally 
deployed the ejb.jar instead of the .ear, because when I tried 
again this morning I discovered that there was an error in the 
application.xml file and the .ear itself wouldn't deploy.  I fixed 
the error, redeployed, and hey presto - the test case works 
correctly!!!  There's still a problem with my application, but I 
finally diagnosed the cause as related to jar file indexes.  
Deleting the META-INF/INDEX.LIST files from all the jars 
cured the problem and allowed the class loader to use the 
Class-Path attributes correctly.

MORAL: don't use jar file indexes unless there's a 1:1 mapping 
from package to jar, across all packages.

----------------------------------------------------------------------

Comment By: Ivan Parra (ioparra)
Date: 2003-10-14 21:25

Message:
Logged In: YES 
user_id=812998

It appears that the problem is the MANIFEST declaration.

You have:
application.xml deploying ejb.jar that has 1 classpath entry.  
JBoss will add that one classpath entry, but will not 
recursively check each child.  

Work around:
If you want to include lib2.jar in your classpatch, add lib2.jar 
to MANIFEST.MF for ejb.jar.  That'll fix the problem.

Solution:
Is an EAR container supposed to recursively run through ALL 
jars that are added to the classpath and add there 
MANIFEST.MF class-path entries?  JBoss is assuming only the 
top level.  The Spec says:

If the by-reference approach is used, the ejb-jar file producer 
does not duplicate the
content of the ejb-client JAR file in the ejb-jar file, but 
instead uses a Manifest Class-Path entry in the
ejb-jar file to specify that the ejb-jar file depends on the ejb-
client JAR at runtime. The use of the
Class-Path entries in the JAR files is explained in the Java 2 
Platform, Enterprise Edition specification
[9].

Neither the j2EE or the ejb spec talks about recursively 
solving all jar dependencies.


----------------------------------------------------------------------

Comment By: Adrian Price (adrianprice)
Date: 2003-10-14 19:35

Message:
Logged In: YES 
user_id=580837

The POST destroyed my formatting, here's the .ear structure 
again:

my-app.ear
____META-INF/application.xml
____my-ejb.jar
________META-INF/MANIFEST.MF Class-Path: lib1.jar
________tld/domain/MyEJB.class
________tld/domain/MyEJBRemote.class
________tld/domain/MyEJBRemoteHome.class
____lib1.jar
________META-INF/MANIFEST.MF Class-Path: lib2.jar
________tld/domain/A.class
____lib2.jar
________tld/domain/B.class

my-client.jar
____META-INF/MANIFEST.MF Main-Class: tld.domain.MyClient
____tld/domain/MyClient.class

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=376685&aid=823636&group_id=22866


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
SourceForge.net hosts over 70,000 Open Source Projects.
See the people who have HELPED US provide better services:
Click here: http://sourceforge.net/supporters.php
_______________________________________________
JBoss-Development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to