Ant build script not seeing refid - ant

I have a build.xml file that includes a common.xml file that defines some refid values. However, my task cannot see the refid value. I have not been able to find a solution on the web and am looking for some help.
I call the genbeans target in the build.xml file. It fails on the xmlbean taskdef with the message Reference my_classpath_jars not found.
build.xml
----------------------------
[includes common.xml]
**my_classpath_jars fails to be seen at this point - defined in common.xml**
<taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean">
<classpath refid="my_classpath_jars"/>
</taskdef>
<!-- Generate the XMLBeans java code from our source XSD file(s) -->
<target name="genbeans" description="Generate XML Bean files" depends="build_my_jar_cpath">
<mkdir dir="${lib}"/>
<xmlbean destfile="${lib}/${appname}Beans.jar" failonerror="true">
<classpath refid="my_classpath_jars"/>
<fileset dir="src/XSD Files" includes="*.xsd, *.wsdl"/>
</xmlbean>
</target>
common.xml
-----------------------------
<target name="build_my_jar_cpath">
<path id="my_classpath_jars">
<fileset dir="${jardir}" includes="**/*.jar" />
</path>
<pathconvert pathsep="${path.separator}" property="myjar.clpath" refid="my_classpath_jars"/>
</target>

When in doubt, use the ant -d switch when calling your target. You'll see a ton of output. Save it to a file and parse through it.
Do that, and the first thing you'll notice in the output is that it's defining your taskdefbefore you have defined your my_classpath_jars. That my_classpath_jars refid is only set when you call that greenbeans target. Your <taskdef> is executed before any of your targets are called.
Either take the definition of my_classpath_jars out of the target greenbeans, or put your <taskdef> in there.

Related

is there a way to make a jar with the Eclipse generated ant script?

To my surprise the build.xml file generated by Eclipse (Neon) for Java has no element containing an invocation of a jar task. As often is the case with code generation I think you have to use it and make no edits so that you can regenerate - or - avoid code generation completely. A comment in the generated file suggests it might be possible to avoid edits by extending the capabilities by importing.
<!-- WARNING: Eclipse auto-generated file.
Any modifications will be overwritten.
To include a user specific buildfile here, simply create one in the same
directory with the processing instruction <?eclipse.ant.import?>
as the first entry and export the buildfile again. -->
I thought I would be able to use the <?eclipse.ant.import?> element in an second file called export.xml. In ant scripting there is supposed to be one project per buildfile so now there is a second project with a dependency on a target in the first project.
Regenerating build.xml reveals that it contains an "import" as expected.
<import file="export.xml"/>
Unfortunately this does not work. Running ant, which I do from the command line, just seems to result in the export/jar project being ignored.
The generated script with the import element (nested on the 7th line)...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="ohana1">
<property environment="env"/>
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.8"/>
<property name="source" value="1.8"/>
<import file="export.xml"/>
<path id="ohana1.classpath">
<pathelement location="bin"/>
<pathelement location="../export/ohana1/commons-collections-3.2.1.jar"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.launch"/>
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="build-subprojects,build-project" name="build"/>
<target name="build-subprojects"/>
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="ohana1.classpath"/>
</javac>
</target>
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</copy>
<unzip dest="${ant.library.dir}">
<patternset includes="jdtCompilerAdapter.jar"/>
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</unzip>
</target>
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
</project>
The export.xml file meant to make a jar...
<?eclipse.ant.import?>
<project basedir="." default="export" name="ohana1Export">
<target depends="build,make-jar" name="export"/>
<target name="make-jar">
<jar destfile="../export/ohana1/${ant.project.name}.jar" basedir="bin"/>
</target>
</project>
Note that the Eclipse Ant editor complains about this export.xml file because the target named build, which is a dependency, does not exist in this project/buildfile. The build target is in the generated build.xml. That error might be coming from a "dumb" editor so I went ahead to do a run of ant. Invoking ant from the command line I find that there is no jar file made.
Should I conclude that Eclipse's ant script generator is useless if you need to export a .jar file and that a human should maintain the ant script that meets all the requirements?
Yes, in my opinion the exported build.xml is useless, as of Eclipse Neon, if the intention is to make a .jar.
Specifically do the following.
Manually write the trivial ant script that exports a .jar. The link at the bottom of this post has verbatim text on what the script might look like. You can use the built-in Xml Editor via New > Other > XML > XML File to create this new file which might be called makeJar.xml and save it. If the icon shown in the Package Explorer is still a plain XML file icon refreshing the project may change the icon to an Ant file icon. In the future, you can use Open With to get the Ant Editor instead of the XML Editor. This script will replace the manual exporting of a .jar that the user would otherwise perform via Eclipse.
This script can be added to Project > Properties > Builders. It would be placed second in the list of Builders. First in the list of Builders is the Java Builder which should already exist. When an Eclipse build is invoked the entire list of Builders will be processed in the order shown in the list of Builders. Thus not only will .class files be generated but also the .jar.
What is achieved is greater automation since the .class generation and .jar generation are now integrated, which arguably was the point of using the exported build.xml in a failed attempt to generate the .jar.
Here is the dialog at Project > Properties > Builders that you can use to create a new Builder. Select New then select Ant Builder. I gave the name makeJar to the new Builder.
Here is the dialog for the new Ant Builder that will allow you to browse to your buildfile which is your manually written Ant script that creates a .jar file. In this example the script is makeJar.xml. It also allows you to browse to the base directory to be used when the script is run.
After setting up the new Builder, a project "clean" or project "build" will create .class files and also the .jar.
Eclipse's documentation on this subject is at the link. Note that it seems impossible to link the exact page that contains the instructions so you have to browse down the documentation tree to the section about "Ant buildfiles as project builders".
Link to Eclipse and Ant

How to compile each jasper file to its own directory?

I'm trying to create a ant script to compile my jasper files, but I have many "srcdir" and "destdir":
<target name="all">
<jrc
srcdir="many..."
destdir="many..."
tempdir="any"
xmlvalidation="true">
<classpath refid="classpath"/>
<include name="**/*.jrxml"/>
</jrc>
</target>
...and I would like it to compile each file to it's own dir. For every ".jrxml" file.
Is there a way?
You can use ant-contrib foreach task to loop over each jrxml file and call the jrc task for each of those. If you don't have it, you'll need to install ant-contrib by copying its JAR file to the lib directory of your Ant installation (if you're using Eclipse, you can add it by going to "Window > Preferences > Ant > Runtime" and adding the JAR into "Ant Home Entries").
The following defines a target "all" that will select all the jrxml files under the current directory. For each of those file, the "jrc" target will be called and the corresponding file will be referenced by the property jrxml.file.
Inside this task, the directory where the jrxml file is located is retrieved with the dirname task and the name of the jrxml file is retrieved with the basename task. The built .jasper file will be created under a folder having the same name as the jrxml file. (It needs to be created first with the mkdir task).
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<target name="all">
<foreach target="jrc" param="jrxml.file">
<path>
<fileset dir=".">
<include name="**/*.jrxml"/>
</fileset>
</path>
</foreach>
</target>
<target name="jrc">
<dirname property="jrxml.dir" file="${jrxml.file}"/>
<basename property="jrxml.filename" file="${jrxml.file}" suffix="jrxml"/>
<mkdir dir="${jrxml.dir}/${jrxml.filename}"/>
<jrc srcdir="${jrxml.dir}"
destdir="${jrxml.dir}/${jrxml.filename}"
tempdir="${jrxml.dir}/${jrxml.filename}"
xmlvalidation="true">
<classpath refid="classpath"/>
<include name="${jrxml.filename}.jrxml"/>
</jrc>
</target>
As an example, if you have a structure:
+folder
+--jrxml
+----Example1.jrxml
+----Example2.jrxml
the result will be
+folder
+--jrxml
+----Example1.jrxml
+----Example1
+------Example1.jasper
+----Example2.jrxml
+----Example2
+------Example2.jasper

How to execute Ant build in command line

I have an Ant build file, and I try to execute it in the command line with the following command:
$ C:\Program Files (x86)\.....>ant -f C:\Silk4J\Automation\iControlSilk4J\build.xml
But nothing happens, and the result is:
BUILD SUCCESSFUL
Total time: 0 seconds
My environment variable is correct.
What is the problem? Here is my build file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- WARNING: Eclipse auto-generated file.
Any modifications will be overwritten.
To include a user specific buildfile here, simply create one in the same
directory with the processing instruction <?eclipse.ant.import?>
as the first entry and export the buildfile again. -->
<project basedir="." default="build" name="iControlSilk4J">
<property environment="env"/>
<property name="ECLIPSE_HOME" value="../../../Program Files (x86)/Silk/SilkTest/eclipse"/>
<property name="junit.output.dir" value="junit"/>
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.6"/>
<property name="source" value="1.6"/>
<path id="Silk Test JTF 13.5.0 Library.libraryclasspath">
<pathelement location="../../../Program Files (x86)/Silk/SilkTest/ng/JTF/silktest-jtf-nodeps.jar"/>
</path>
<path id="JUnit 4.libraryclasspath">
<pathelement location="${ECLIPSE_HOME}/plugins/org.junit_4.8.2.v4_8_2_v20110321-1705/junit.jar"/>
<pathelement location="${ECLIPSE_HOME}/plugins/org.hamcrest.core_1.1.0.v20090501071000.jar"/>
</path>
<path id="iControlSilk4J.classpath">
<pathelement location="bin"/>
<pathelement location="lib/apache-log4j.jar"/>
<pathelement location="lib/commons-io-2.4.jar"/>
<pathelement location="lib/commons-lang3-3.1.jar"/>
<pathelement location="lib/junit.jar"/>
<pathelement location="lib/org.hamcrest.core_1.1.0.v20090501071000.jar"/>
<pathelement location="lib/silktest-jtf-nodeps.jar"/>
<path refid="Silk Test JTF 13.5.0 Library.libraryclasspath"/>
<path refid="JUnit 4.libraryclasspath"/>
<pathelement location="../../../Users/Admin/Desktop/java-mail-1.4.4.jar"/>
<pathelement location="../../../Users/Admin/Desktop/javax.activation.jar"/>
<pathelement location="lib/joda-time-2.3.jar"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="build-subprojects,build-project" name="build"/>
<target name="build-subprojects"/>
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="iControlSilk4J.classpath"/>
</javac>
</target>
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</copy>
<unzip dest="${ant.library.dir}">
<patternset includes="jdtCompilerAdapter.jar"/>
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</unzip>
</target>
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
...
Go to the Ant website and download. This way, you have a copy of Ant outside of Eclipse. I recommend to put it under the C:\ant directory. This way, it doesn't have any spaces in the directory names. In your System Control Panel, set the Environment Variable ANT_HOME to this directory, then pre-pend to the System PATHvariable, %ANT_HOME%\bin. This way, you don't have to put in the whole directory name.
Assuming you did the above, try this:
C:\> cd \Silk4J\Automation\iControlSilk4J
C:\Silk4J\Automation\iControlSilk4J> ant -d build
This will do several things:
It will eliminate the possibility that the problem is with Eclipe's version of Ant.
It is way easier to type
Since you're executing the build.xml in the directory where it exists, you don't end up with the possibility that your Ant build can't locate a particular directory.
The -d will print out a lot of output, so you might want to capture it, or set your terminal buffer to something like 99999, and run cls first to clear out the buffer. This way, you'll capture all of the output from the beginning in the terminal buffer.
Let's see how Ant should be executing. You didn't specify any targets to execute, so Ant should be taking the default build target. Here it is:
<target depends="build-subprojects,build-project" name="build"/>
The build target does nothing itself. However, it depends upon two other targets, so these will be called first:
The first target is build-subprojects:
<target name="build-subprojects"/>
This does nothing at all. It doesn't even have a dependency.
The next target specified is build-project does have code:
<target depends="init" name="build-project">
This target does contain tasks, and some dependent targets. Before build-project executes, it will first run the init target:
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
This target creates a directory called bin, then copies all files under the src tree with the suffix *.java over to the bin directory. The includeemptydirs mean that directories without non-java code will not be created.
Ant uses a scheme to do minimal work. For example, if the bin directory is created, the <mkdir/> task is not executed. Also, if a file was previously copied, or there are no non-Java files in your src directory tree, the <copy/> task won't run. However, the init target will still be executed.
Next, we go back to our previous build-project target:
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="iControlSilk4J.classpath"/>
</javac>
</target>
Look at this line:
<echo message="${ant.project.name}: ${ant.file}"/>
That should have always executed. Did your output print:
[echo] iControlSilk4J: C:\Silk4J\Automation\iControlSilk4J\build.xml
Maybe you didn't realize that was from your build.
After that, it runs the <javac/> task. That is, if there's any files to actually compile. Again, Ant tries to avoid work it doesn't have to do. If all of the *.java files have previously been compiled, the <javac/> task won't execute.
And, that's the end of the build. Your build might not have done anything simply because there was nothing to do. You can try running the clean task, and then build:
C:\Silk4J\Automation\iControlSilk4J> ant -d clean build
However, Ant usually prints the target being executed. You should have seen this:
init:
build-subprojects:
build-projects:
[echo] iControlSilk4J: C:\Silk4J\Automation\iControlSilk4J\build.xml
build:
Build Successful
Note that the targets are all printed out in order they're executed, and the tasks are printed out as they are executed. However, if there's nothing to compile, or nothing to copy, then you won't see these tasks being executed. Does this look like your output? If so, it could be there's nothing to do.
If the bin directory already exists, <mkdir/> isn't going to execute.
If there are no non-Java files in src, or they have already been copied into bin, the <copy/> task won't execute.
If there are no Java file in your src directory, or they have already been compiled, the <java/> task won't run.
If you look at the output from the -d debug, you'll see Ant looking at a task, then explaining why a particular task wasn't executed. Plus, the debug option will explain how Ant decides what tasks to execute.
See if that helps.
Try running all targets individually to check that all are running correct
run ant target name to run a target individually
e.g. ant build-project
Also the default target you specified is
project basedir="." default="build" name="iControlSilk4J"
This will only execute build-subprojects,build-project and init
is it still actual?
As I can see you wrote <target depends="build-subprojects,build-project" name="build"/>, then you wrote <target name="build-subprojects"/> (it does nothing). Could it be a reason?
Does this <echo message="${ant.project.name}: ${ant.file}"/> print appropriate message? If no then target is not running.
Take a look at the next link http://www.sqaforums.com/showflat.php?Number=623277

How to avoid running ant tasks on source files that have not changed?

I have an ant task that executes some command on a list of files.
I would like, on consecutive builds, to avoid from re-running the command on files that have passed the command with success and haven't changed.
For example: (here the command is xmllint)
<target name="xmllint-files">
<apply executable="xmllint">
<srcfile/>
<fileset dir="." includes="*.xml">
<modified/>
</fileset>
</apply>
</target>
The problem is that even the files where xmlint fails are considered as modified and therefore xmllint will not be re-run on them on consecutive builds. Obviously, this is not the desired behavior.
Two remarks:
I am looking for a general solution and not only a solution for xmllint.
I want to solve the problem totally inside ant without creating
external scripts.
This code uses the Groovy ANT task to do the following:
Implement a custom groovy selector, selecting the XML files to be processed based on a MD5 checksum check.
Invoke xmllint on each file and store it's checksum upon successful completion (This prevents re-execution of xmllint unless the file's contents are changed.
Example:
<project name="demo" default="xmllint">
<!--
======================
Groovy task dependency
======================
-->
<path id="build.path">
<pathelement location="jars/groovy-all-1.8.6.jar"/>
</path>
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<!--
==============================================
Select files to be processed
MD5 checksums located in "checksums" directory
==============================================
-->
<target name="select-files">
<fileset id="unprocessedfiles" dir=".">
<include name="*.xml"/>
<exclude name="build.xml"/>
<scriptselector language="groovy" classpathref="build.path">
def ant = new AntBuilder()
ant.checksum(file:filename, toDir:"checksums", verifyProperty:"isMD5ok")
self.selected = (ant.project.properties.isMD5ok == "false") ? true : false
</scriptselector>
</fileset>
</target>
<!--
=============================================================
Process each file
Checksum is saved upon command success, prevents reprocessing
=============================================================
-->
<target name="xmllint" depends="select-files">
<groovy>
project.references.unprocessedfiles.each { file ->
ant.exec(executable:"xmllint", resultproperty:"cmdExit") {
arg(value:file)
}
if (properties.cmdExit == "0") {
ant.checksum(file:file.toString(), toDir:"checksums")
}
}
</groovy>
</target>
</project>
Note:
This complex requirement cannot be implemented using the original apply ANT task. One call to xmllint command might succeed whereas another might fail.
A subdirectory called "checksums" is created to store the MD5 checksum files.
The groovy jar can be downloaded from Maven Central
Original answer
Use the ANT modified selector
<project name="demo" default="xmllint">
<target name="xmllint">
<apply executable="xmllint">
<srcfile/>
<fileset dir="." includes="*.xml">
<modified/>
</fileset>
</apply>
</target>
</project>
A property file called "cache.properties" will be created in the build directory. It records file digests, used determine if the file has been changed since the last build run.

Making jUnit output info and compile to /build folder

I have the following Ant buildfile:
<?xml version="1.0"?>
<!-- the value of the default attr must be one of the targets. -->
<project name="Money" default="build-source" basedir=".">
<description>The Money project build file.</description>
<property name="src" location="."/>
<property name="build" location="build"/>
<property name="junit" location="lib/junit-4.9b3.jar"/>
<path id="_classpath">
<pathelement path="${junit}"/>
<pathelement path="${build}"/>
</path>
<target name="prepare">
<mkdir dir="${build}"/>
</target>
<target name="build-source" depends="prepare"
description="compile the source ">
<javac srcdir="${src}" destdir="${build}">
<classpath refid="_classpath"/>
</javac>
</target>
<target name="run" depends="build-source">
<junit printsummary="on" showoutput="on">
<test name="money.MoneyTest"/>
<classpath refid="_classpath"/>
</junit>
</target>
</project>
It's pretty basic - I'm just trying to get this thing to run properly. What I don't get is: 1) Why does it output the compiled files to a /build/money directory? I want the output directory to be just /build, given this directory structure for my files:
build/
build.xml
lib/
src/
test/
2) When there are tests that don't pass, it says "Test money.MoneyTest FAILED". I'd like it to output info about the failure, expected / actual values, line number, etc.
I can't figure this out by staring at the buildfile above. Any advice?
It outputs the compiled files under build, creating a directory structure that corresponds to the layout of your packages.
Since you put your classes in the money package, the output will be under build/money. If you put your classes under a org.example.foo package, your output would be in the build/org/example/foo directory.
To have your .class files in build, you would have to use the default package.
Edit
I assume your source files have a package money; declaration, as in:
package money;
public class MoneyTest {
...
}
If you add a <formatter> element, detailed reports about test failures will be written to an output file (by default, named TEST-name). See also the Ant Junit Task Documentation.
<junit printsummary="withOutAndErr" showoutput="on">
<formatter type="plain"/>
<test name="money.MoneyTest"/>
<classpath refid="_classpath"/>
</junit>
I have not found a way to directly print the failed tests reports to standard output.

Resources