ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Conor MacNeill" <>
Subject Re: Running junit tests that access EJBs
Date Wed, 11 Apr 2001 11:31:55 GMT

There are (unfortunately) a multitude of issues at play here.

Firstly, there is a copy of javax.naming.InitialContext on both the system
classpath (certainly with JDK 1.3) and the junit task's classpath. The Ant
classloader is normally setup to use the java.* and javax.* implementations
from the system classpath. Any classes which exist on the system classpath
from these packages will be delegated to the system classloader.
*Normally*, you'd expect that any classes which are subsequently loaded by
those classes must be loaded by the system class loader. It can't come back
out to the AntClassLoader.

It wasn't my intention, when I wrote the AntClassLoader, that it would
always load these classes from the system classloader. That change was made
to handle some subtle LinkageErrors. Whilst that issue may not still be a
problem it would be difficult to revert the behaviour now. I have
encountered exactly the problem you mention here. As a result I have played
with adding the mode to the classloader where I can tell it to load javax.*
from the AntClassLoader classpath.

I tried this change out and indeed I can get the
javax.naming.InitialContext class to load through the AntClassLoader rather
than the system class loader. This didn't fix the problem, however, which
is why I highlighted the "Normally" above. If you look at the
javax.naming.InitialContext code that comes with the JDK (1.3 in the
src.jar and it seems the same classes are in weblogic's weblogic.jar) you
will see that the initial context factory uses the classloader from
Thread.getContextClassLoader(). What this means is that whatever
classloader is used to load the InitialContext, the given factory class
will be loaded from the classloader associated with the current thread. In
the case of Ant, the current thread will have the system classpath.

Ironically, this mechanism seems designed to load factory classes from the
caller's classloader even when javax.naming.InitialContext is loaded from
the system classloader. In our case it does the exact opposite :-). The
answer would be to have the AntClassLoader associated with the current
Thread by calling setContextClassLoader. That would require reflection in
Ant 1.x. Also, this mechanism is not really used by most code that I am
aware of, so while you may get the factory to load, I wonder what else
would still not load..

The solution I have used is to fork the junit task <junit fork="yes"> and
          <pathelement path="${java.class.path}"/>
in the classpath you give it (so it can find the necessary Ant classes).

Not pretty but workable.

Sorry for the long-winded explanation.

----- Original Message -----
From: "Jim Doyle" <>
To: <>
Sent: Wednesday, April 11, 2001 6:18 AM
Subject: Running junit tests that access EJBs

> Hi,
>     I looked on this list for some suggestions about how to use Ant to
> manage unit tests for EJBs,
> and it seemed that a couple people had the approach of running the
> server in one Ant instance (using wlrun) and running the junit test in
> another Ant instance.  I've got the server part working fine, but I'm
> having trouble with my client.
>     I can run the JUnit test from the command line with no problem.  I
> can also run it with a forked java task, like this:
>   <property name="jdbc.driver.class.path"
>   <property name="weblogic.home"
> value="c:/JavaTools/weblogic/weblogic51"/>
>   <property name="weblogic.class.path"
>   <target name="" depends="compile">
>     <java classname="junit.textui.TestRunner" fork="yes">
>       <sysproperty key="java.naming.provider.url"
> value="t3://localhost:7001"/>
>       <arg value="PowerSystemEjbTest"/>
>       <classpath
>     </java>
>   </target>
> But I would like to use the junit task, which I use for my other unit
> tests, and that doesn't work unless I put weblogic in my CLASSPATH for
> Ant.  I've tried:
>   <target name="test.ejb.cp" depends="compile">
>     <junit haltonfailure="yes">
>       <sysproperty key="java.naming.provider.url"
> value="t3://localhost:7001"/>
>       <classpath path="${weblogic.class.path}"/>
>       <batchtest>
>         <formatter type="plain" usefile="no"/>
>         <fileset dir="${basedir}">
>           <include name=""/>
>         </fileset>
>       </batchtest>
>     </junit>
>   </target>
> but it throws a "java.lang.NoClassDefFoundError:
> javax/ejb/CreateException".
> I've also tried eliminating the classpath element, and it throws a
> "javax.naming.NoInitialContextException,
> java.lang.ClassNotFoundException:
> weblogic.jndi.WLInitialContextFactory".
> If I put my weblogic classpath into the Ant classpath, it works OK, but
> I'd prefer to have the classpath in my build file.
> So:
> 1) Does anybody know why the class loading is behaving the way it does?
> I can dump some debugging output if it would help.
> 2) How are others out there running JUnit tests that use EJBs?  Do you
> use a forked java task, or put weblogic in Ant's CLASSPATH, or is there
> some other way?
> Thanks for your help!
> --
> Jim Doyle

View raw message