Add classpath of third party jar in ant build file - ant

I want to use a third party jar file to be used in my ant project.
I guess that I should add something in build.xml file.
Actually I want to add Jsoup dependency in my build file.
I have read somethings after google search but i could not find out.
I already have tried
<classloader loader="system">
<classpath>
<fileset dir="${basedir}" includes="jsoup-1.6.2.jar"/>
</classpath>
</classloader>
Can someone tell me how can I do this ?

Here is one way to add a jar to your javac classpath.
<javac srcdir="${src}" destdir="${classes}">
<classpath>
<pathelement location="jsoup-1.6.2.jar"/>
</classpath>
</javac>
You could also define the classpath outside the scope of javac (e.g. at top-level of your build file) and then refer to it by id in your javac task.

Thanks for your reply. But later on I managed to solve the problem.
Since this is ant project. There is an ivy.xml so just adding ant dependency of jsoup in ivy.xml works fine.

Related

Compiling a build.xml file using Ant

I recently installed Ant 1.8.4 and JasperReports 4.6.0 on my Ubuntu machine.
The following environmental variables were set on my account:
PATH=$PATH:/opt/ant/bin
export PATH
export ANT_HOME=/opt/ant
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk-amd64
When I try to run a demo build file in the JasperReports demo samples directory using the command ant I get the following error:
Buildfile: build.xml
BUILD FAILED
/opt/jasperreports-4.6.0/demo/samples/antcompile/build.xml:3: The following
error occurred while executing this line:
jar:file:/opt/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml:37: Problem: failed to create task or type componentdef
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
Any help in solving this problem will be super helpful.
The snippet of build.xml file:
<project name="antcompile" default="test" basedir=".">
<description>Shows how multiple JRXML files can be compiled in batch mode using ANT.</description>
<path id="classpath">
<pathelement location="../../../build/classes"/>
<fileset dir="../../../lib">
<include name="**/*.jar"/>
</fileset>
</path>
<path id="runClasspath">
<path refid="classpath"/>
<pathelement location="../../fonts"/>
<pathelement location="./build/classes"/>
</path>
<taskdef name="jrc" classname="net.sf.jasperreports.ant.JRAntCompileTask">
<classpath refid="classpath"/>
</taskdef>
<target name="javac" description="Compiles the Java source files used in the report designs.">
<mkdir dir="./build/classes"/>
<javac srcdir="./src" destdir="./build/classes" debug="true" optimize="false" deprecation="false"/>
</target>
<target name="compile1" description="Compiles report designs specified using the "srcdir" in the <jrc> tag."> <!-- 27 row # -->
<mkdir dir="./build/reports"/>
<jrc
srcdir="./reports"
destdir="./build/reports"
tempdir="./build/reports"
keepjava="true"
xmlvalidation="true">
<classpath refid="runClasspath"/>
<include name="**/*.jrxml"/>
</jrc>
</target>
This Ant script is using custom task jrc.
As you can see from the snippet below (this is build.xml file from the jasperreports-4.6.0/demo/samples/antcompile folder), this task's definition refers the classpath from the same build file.
<path id="classpath">
<pathelement location="../../../build/classes"/>
<fileset dir="../../../lib">
<include name="**/*.jar"/>
</fileset>
</path>
...
<taskdef name="jrc" classname="net.sf.jasperreports.ant.JRAntCompileTask">
<classpath refid="classpath"/>
</taskdef>
You should check the ../../../build/classes folder (in JasperReports package's folder structure which contains samples) - the net.sf.jasperreports.ant.JRAntCompileTask class must be there.
In other words you should put this class (or jasperreports-4.6.0.jar) to the classpath (path id="classpath").
Another probable source of your problem is the version of Ant package.
You can read about Project#createTask complains it wouldn't find task componentdef issue on Ant's bugtracker and project.createTask() not working with ant-1.8.2 post.
I made it work by changing the following element in my CLASSPATH, /opt/jasperreports-4.6.0/lib/ant-1.7.1.jar to /opt/ant/lib/ant.jar.
Thanks to Alex for posting the helpful links!
Anjan
You're going have to help us out a bit here...
Are you building JasperReports-4.6.0? Or, are you using JasperReports as part of your build.xml? Is this a test build.xml demoing JasperReports?
The error says Check that any custom tasks/types have been declared, so what is the Ant task in line #37? Is there a in the build.xml? Does it have a classpath defined? If you have a taskdef, please let us see what it is, and what the custom task is.
I'm downloading iReport to see if I can figure out what you're doing, but it's taking 15 minutes. I bet you're supposed to put some jar into $ANT_HOME/lib. Maybe that JasperReports or iReport jarfile.
As soon as I can download iReport and see what you're talking about, I'll update my answer.
Meanwhile, include the relevant code around line #35 in your build.xml and the taskdef task in your build.xml.
Finished downloading iReport and there is no build.xml file in it. You're going to have to post your code, so we can look at it.
Again, my assumption is that there's some jar file that they assumed you'd stick in /opt/ant/lib and didn't.

Including maven convention folders to classpath in IVY

The reason we are using IVY is that we already have ANT scripts. Meaning, there is no maven compatible folders by default.
We had to create such convention.
Now, I already implemented the IVYing. After resolve, I do the
<ivy:cachepath pathid="ivy.test.classpath" conf="test" settingsref="ivy.ref" />
The problem with this, it doesn't include the
src/test/java , src/test/resources
What is the best way of including those.
What I'm currently doing is creating another classpath (postfixed with .extended) that includes the original classpath along with the new folders.
Is there an 'IVYier' way to do it? maybe add something in the dependency file ivy.xml or a way to tell it to act maven.
Thanks in advance
Why do you need to add the source dirs to the classpath?
I typically only need to add the compiled classes directory into a classpath and that is typically easier to do directly in the few tasks like Junit that needs to be configured in this manner.
For example:
<junit ....>
<classpath>
<path refid="runtime.path"/>
<pathelement path="${classes.dir}"/>
</classpath>
..
</junit>

where to find missing optional ant tasks?

I wanted to have a look which system properties are set here (and to which values), so the easiest way (if not writing a new Java program here) would be adding some lines to my ant build script:
<target name="properties">
<echoproperties/>
</target>
But running ant gives my this error message:
/u/ebermann/projektoj/stackoverflow-examples/build.xml:19: Problem: failed to create task or type echoproperties
Cause: the class org.apache.tools.ant.taskdefs.optional.EchoProperties was not found.
This looks like one of Ant's optional components.
Action: Check that the appropriate optional JAR exists in
-/usr/share/ant/lib
-/u/ebermann/.ant/lib
-a directory added on the command line with the -lib argument
Do not panic, this is a common problem.
The commonest cause is a missing JAR.
This is not a bug; it is a configuration problem
Okay, so I don't panic, but wonder what to do.
I have Ant 1.7.1 here (an OpenSUSE system), and sadly no documentation for this version, and I'm not root to install either a current ant version or the documentation for the old version (I just downloaded it and it still does not say which jar file is needed here). Of the directories listed above, only /usr/share/ant/lib exists, but it contains nothing like optional.
I would want to download the necessary jar file and put it in my home directory, but where to find it? The ant download archive contains nothing like that, and I have no idea where else to search. (I did google a bit, but did not find anything.
So, can someone give me some pointers where to find the right jar file?
(I suppose the solution is quite easy, and something is just blocking my view.)
After vahapt's answer, I downloaded the file from the apache repository, and put it into the directory /u/ebermann/.ant/lib mentioned by the error message. Running ant properties again - the same result as above.
$ jar -tf /u/ebermann/.ant/lib/ant-nodeps-1.7.1.jar | grep 'EchoProperties.class'
org/apache/tools/ant/taskdefs/optional/EchoProperties.class
This looks like it should work - is the error message simply wrong?
If I put it directly into the CLASSPATH, it works:
$ CLASSPATH=/u/ebermann/.ant/lib/ant-nodeps-1.7.1.jar ant properties
Buildfile: build.xml
properties:
[echoproperties] #Ant properties
[echoproperties] #Thu Mar 10 00:46:22 CET 2011
...
[echoproperties] user.name=ebermann
[echoproperties] user.timezone=
BUILD SUCCESSFUL
Total time: 0 seconds
I don't want to change my normal CLASSPATH variable, and it should work by putting it into this directory, or did I understand something wrong?
Any ideas, or is this an ant bug?
(Also, why is this file nowhere mentioned in the ant documentation?)
Edit:
After the answer from vahapt, my ant build-file looks like this:
<project name="stackoverflow-examples" basedir=".">
<target name="echoproperties.prepare">
<available property="echoproperties.works"
classname="org.apache.tools.ant.taskdefs.optional.EchoProperties"
/>
</target>
<target name="echoproperties.init"
depends="echoproperties.prepare"
unless="echoproperties.works">
<taskdef name="echoproperties" classname="org.apache.tools.ant.taskdefs.optional.EchoProperties">
<classpath>
<fileset dir="${user.home}/.ant/lib">
<include name="ant-nodeps.jar" />
</fileset>
</classpath>
</taskdef>
</target>
<target name="properties" depends="echoproperties.init">
<echoproperties/>
</target>
</project>
This re-registers the task only if it is not already in the ant classpath. (Thus it should also work for complete ant installations which do not have this file in the home directory).
I would still say that This is not a bug; it is a configuration problem is not totally right, even more as putting the file in the indicated directory does not help.
One more interesting observation: The nodeps.jar in ${user.home}/.ant/lib (i.e. now /u/ebermann/.ant/lib/ant-nodeps.jar) is already in the class path (the one shown by ${java.class.path}, but this seems not to help for <echoproperties> to work without this taskdef.
So, this works too:
<target name="echoproperties.init"
depends="echoproperties.prepare"
unless="echoproperties.works">
<taskdef name="echoproperties"
classname="org.apache.tools.ant.taskdefs.optional.EchoProperties"
classpath="${java.class.path}" />
</target>
When you make a google search, results point to ant-nodeps-1.7.1.jar
Make sure that jar exists and you've added it into the classpath
For the second part of your question:
SOLUTION 1. You do not need to modify your CLASSPATH variable. Instead you might add it by adding the parameter -cp [JAR FILE LOCATION] (-cp is for "java" executable)
SOLUTION 2. Jar files are simply zip files, open ant-nodeps.jar copy its content to ant.jar throw away ant-nodeps.jar
SOLUTION 3. See the sample below. taskdef is a ant feature that loads a jar or a class into ClassLoader hierarchy. (You load the class before using it, works like a charm)
<?xml version="1.0" encoding="ASCII"?>
<project name="Test" default="properties" basedir=".">
<target name="properties" depends="init">
<echoproperties/>
</target>
<target name="init">
<taskdef name="echoproperties" classname="org.apache.tools.ant.taskdefs.optional.EchoProperties">
<classpath>
<fileset dir="${ant.library.dir}">
<include name="ant-nodeps.jar" />
</fileset>
</classpath>
</taskdef>
</target>
</project>
I downloaded Ant 1.7.1 and looked in the documentation that came with it. There it described echoproperties as an optional task, but didn't mention where to get the jarfile for this optional task.
Looking inside the lib folder, I discovered the ant-nodeps.jar. Apparently, it was included with Ant 1.7.1.
I would recommend that you download and install Ant 1.8. Since Ant is a Java jar file, it's not really all that difficult to install the latest and greatest version.
I looked on my Mac, and /usr/bin/ant is a link to /usr/share/ant/bin and /usr/share/ant/ is a link to /usr/share/java/ant-1.8.2. So, all I have to do is point /usr/share/ant/bin/ to the correct version of Ant.
In Ant 1.8.2, echoproperties is now a standard task.

How can I specify the path of a JAR in an ant buildfile?

I am executing lot of scp and sshexec and other remote commands from an ant build script. These commands don't work if jsch.jar isn't in the ant lib directory. To make it work, I copied the JAR into the ant lib directory, but this is not a good solution, as anyone else wanting to run the script would have to do the same thing. To run the ant target from Teamcity, we will have to explicitly set the path of the lib file.
Is there a way I can specify the path of the JAR in the ant build XML itself?
Thanks all for your answers. I am managed to get it work with classloader task. This is what I did.
<project basedir="." >
<property environment="env"/>
<taskdef resource="net/jtools/classloadertask/antlib.xml">
<classpath>
<fileset dir="${basedir}/lib" includes="ant-classloader*.jar"/>
</classpath>
</taskdef>
<!--Add JSCH jar to the classpath-->
<classloader loader="system">
<classpath>
<fileset dir="${basedir}/lib" includes="jsch*.jar"/>
</classpath>
</classloader>
<target name="Test">
<scp todir="user1:pass1#server1:/tmp" trust="true" >
<fileset dir="dir1">
<include name="test.txt" />
</fileset>
</scp>
</target>
</project>
As you can see here, I didn't have to give any dependant target for my "Test" target, it just works. It uses classloader, which appends jsch.jar to the system classloader.
One possible work around would be to use the -lib command line option to tell ant where to look for additional jars. Perhaps you could create a wrapper script that calls ant with this option set.
Another way would be to move the ant-jsch.jar file (this is the jar that comes with ant that defines the tasks, not the jsch.jar file you need to download separately) out of your ant lib directory, and create a taskdef for your ssh task separate to the built in one, then set the classpath for this task to the jsch.jar and the ant-jsch.jar:
<taskdef name="sshexec"
classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec">
<classpath>
<pathelement location="jsch-0.1.44.jar"/>
<pathelement location="ant-jsch.jar" />
</classpath>
</taskdef>
I'm not sure this will help you though, since it also involves making changes to the lib directory.
As far as I'm aware, it's not currently possible to specify the extra jars required for the built in tasks in the build file itself in general. There are some special cases, like junit for instance.
To ensure your build is more cross platform I'd suggest using dependency management. The ivy plug-in can automatically install the version of your build's plugin at build-time.
This approach means the last jar you'll ever need to install into your ANT lib is ivy-2.2.0.jar :-)
First declare your project's dependencies in the file ivy.xml
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="anttask" description="Jars implementing ANT tasks"/>
</configurations>
<dependencies>
<dependency org="com.jcraft" name="jsch" rev="0.1.42" conf="anttask->default"/>
</dependencies>
</ivy-module>
Within your build.xml run ivy and use it to populate a custom classpath based on the ivy configuration:
<target name='init' description='Resolve project dependencies and set classpaths'>
<ivy:resolve/>
<ivy:cachepath pathid="anttask.path" conf="anttask"/>
</target>
Finally, elsewhere in your build declare your ANT tasks using the class path now automatically populated by ivy.
<target name='dosomething' depends="init">
<taskdef name="sshexec"
classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec"
classpathref="anttask.path"/>
..
..
</target>
This approach works for all ANT plug-ins, most of which are available in the central Maven repository. The second benefit is that it's easy to upgrade the plug-in versions across all builds.

Classpath for taskdef?

I am defining a new task in Ant.
I exported it as a jar and added to my buildfile:
<taskdef classname="X" classpath="Y.jar"/>
The problem is that this fails at runtime.
It tells me it didn't find the class.
By adding the jar to the classpath, it is corrected.
My question is: Is there a way that I can refer to my jar from the Ant buildfile, without changing the classpath?
If you know the path of your jar, inside ant script you can define the classpath for your own task.
<taskdef name="myTaskName" classname="com.myorg.myclass">
<classpath>
<pathelement location="pathToMyJar.jar"/>
</classpath>
</taskdef>
Yes. I'm assuming that you looked at the doc for taskdef, which just shows the task name and implementing class. However, taskdef subclasses typedef, and if you look at the doc for the latter you'll see that there's also a classpath attribute.
HOWEVER, using this attribute means that your ant scripts are tied to a particular environment; they aren't very portable. A far better approach is to pass the classpath into Ant, using the -lib invocation option.

Resources