views:

6047

answers:

4

I am trying to use the axis-java2wsdl ant task to create a wsdl from one of my java classes, but I cannot get the classpath correct.

I am using Ubuntu's libaxis-java package which installs axis-ant.jar in $ANT_HOME/lib and axis.jar in /usr/share/java. The interesting parts of my build.xml look like this:

<property name="library.dir" value="lib"/>
<property name="system.library.dir" value="/usr/share/java"/>
<path id="libraries">
    <fileset dir="${library.dir}">
     <include name="*.jar"/>
    </fileset>
    <fileset dir="${system.library.dir}">
     <include name="*.jar"/>
    </fileset>
</path>

<target name="genwsdl" depends="compile">
    <taskdef resource="axis-tasks.properties" classpathref="libraries"/>
    <axis-java2wsdl>
            details omitted
    </axis-java2wsdl>
</target>

Running ant genwsdl results in:

/build.xml:50: taskdef A class needed by class
org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask
cannot be found: org/apache/axis/utils/DefaultAuthenticator

Ant is able to find the definition of the axis-java2wsdl task, because axis-ant.jar is in $ANT_HOME/lib, but it cannot find classes in axis.jar, even though that jar is on the path defined by "libraries"

I know it's a classpath issue because I was able to get past DefaultAuthenticator to other class's not found by symlinking axis.jar into $ANT_HOME/lib. How can I get the taskdef to recognize jar files in /usr/share/lib or my project's local lib directory without symlinking everything into $ANT_HOME/lib?

EDIT:

I was finally able to successfully generate the wsdl with this line:

ant -lib /usr/share/java/axis.jar -lib /usr/share/java/jaxrpc.jar -lib /usr/share/java/wsdl4j.jar -lib /usr/share/java/commons-logging.jar -lib /usr/share/java/commons-discovery.jar -lib build genwsdl

I would still very much appreciate if somebody could tell me what I'm doing wrong in not being able to define those libraries in build.xml

+2  A: 

Ant mechanism for adding libraries is:

  • via command line argument -lib
  • adding to ${user.home}/.ant/lib
  • adding to ${ant.home}/lib

Only. The manual doesn't mention anything about using the system.library.dir property. Probably it pretty much ignored for this purpose.

Also, run ant in verbose mode ( and -verbose ) to see what is doing under the hood.

OscarRyz
system.library.dir is a property that I defined, and is being used successfully by the classpathref in the javac task. Why wouldn't it be used in the taskdef task? It seems strange that you can add libraries with a <path> for compiling, but not for running an external task.
Ryan Ahearn
Because, that "value" is used for a "program" that will run ( javac ). But attempting to use it for a program that is already running won't work ( the program already running is ant ).
OscarRyz
For instance, the "javac" task is defined when the ant is running. But the arguments to javac doesn't. When you use the property you're defining the arguments to javac and then you run it. In the other hand your optional task doesn't exists when ant is already running. Even if you attempt to use...
OscarRyz
.. the property, the script fails by not having a source where that task is defined. By using one of the listed strategies, you're allowing to ant to define where it should look for that task.
OscarRyz
This could be a workaround. Load the property and start a new ant task using the "ant task". See this: http://stackoverflow.com/questions/422848/ant-how-to-modify-java-library-path-in-a-buildfile#422869
OscarRyz
Well, it knows where to find the task, it just couldn't find classes that the task needed to run correctly. Thanks for your help.
Ryan Ahearn
+2  A: 

In general, this works. But you need to check very carefully which classes are where.

If your task class can be loaded in a classloader higher up in the classloader hierarchy (like CLASSPATH or ANT_HOME/lib) then your classpathref will simply get ignored.

Read the FAQ entry for more details.

Ant's class loader implementation uses Java's delegation model

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When called upon to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the bootstrap class loader, does not itself have a parent but may serve as the parent of a ClassLoader instance.

Note: running ant -diagnostics can help too.

VonC
That seems like bad behavior, to ignore the classpathref, but it is confirmed by the fact that it all works when I move axis-ant.jar from $ANT_HOME/lib to the /usr/share/java directory that I referenced in the libraries path.
Ryan Ahearn
A: 

Why not just take the simplest option and specify the classpath in your <taskdef>?

<taskdef resource="axis-tasks.properties">
    <classpath>
        <fileset file="/path/to/axis/jars"/>
    </classpath>
</taskdef>

Or create a second <classpath> entry that subsets library.dir?

<path id="axis-tools-classpath">
    <fileset dir="/path/to/axis/home">
        <include name="*.jar"/>
    </fileset>
    <path refid="library.dir"/>
</path>

Messing around with ${ant.home}/lib is not such a good idea and can almost always be avoided.

matt b
taskdef is ignoring the classpathref and also ignoring any direct classpath in it's task. I believe the problem is as VonC stated and the axis-ant.jar is found in a classloader that cannot find axis.jar so the solution is to either use -lib or sumlinks in ~/.ant/lib
Ryan Ahearn
Perhaps you need to resolve the layout of your libraries then - sounds like you could address the problem by making sure that whatever classloader finds axis-ant.jar also has an axis.jar available to it.
matt b
Agreed, the layout of the libraries is not ideal. It is the layout that is default after you install ant and libaxis-java packages in Ubuntu. But also not ideal is moving around those packages or throwing a bunch of symlinks in $ANT_HOME/lib.
Ryan Ahearn
I am generally happy with the solution of adding a shell script to the project that calls ant with the correct -lib arguments.
Ryan Ahearn
A: 

It works for me to specify the classpath directly in the taskdef task, as menstioned by matt b. For my project I find it useful to include the taskdef library in the project folder and specify the classpath in the ant build file, to simply setup on other development pcs. I use the following taskdef:

<taskdef resource="antenna.properties" classpath="${myprojectroot}/lib/antenna-bin-1.2.1-beta.jar"/>

Note that this might not work for versions of ant earlier than 1.7.0.

Ralf