I wrote two different custom Ant tasks. They are trying to share data through a static member in a base class. This is not working for me.
I assume I am using static members correctly within Java. I think this is a dynamic loading issue with the Java VM. However, I am a relative newbie with Java.
Since Ant custom tasks are mapped at runtime using the taskdef task, the Ant build engine must dynamically load this code via java.lang.reflect.Constructor.newInstance().
Is there a trick to make this work?
Note: This works fine in “regular” Java code… it is the dynamic loading of Ant that is the issue.
Example classes:
import org.apache.tools.ant.Task;
public class AntCustomTaskShared extends Task {
private static Integer _static_bigdata = null;
public Integer get_bigdata() {
if (_static_bigdata == null) {
log("alloc"); // from ant Task class
_static_bigdata = new Integer(0);
}
return _static_bigdata;
}
}
import org.apache.tools.ant.BuildException;
public class AntCustomTask1 extends AntCustomTaskShared {
public void execute() throws BuildException {
Integer big_data = get_bigdata(); // "alloc" is printed
// do stuff with big_data
log("I'm doing big stuff");
}
}
import org.apache.tools.ant.BuildException;
public class AntCustomTask2 extends AntCustomTaskShared {
public void execute() throws BuildException {
Integer big_data = get_bigdata(); // "alloc" is printed (again)
// do stuff with big_data
log("I'm doing big stuff again");
}
}
Example Ant build.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyTask" basedir="." default="init">
<target name="init"
description="test the custom task"
>
<taskdef name="CustomTask1"
classname="AntCustomTask1"
classpath="C:\my_custom_ant_task_class_files"
/>
<taskdef name="CustomTask2"
classname="AntCustomTask2"
classpath="C:\my_custom_ant_task_class_files"
/>
<CustomTask1/>
<CustomTask2/>
</target>
</project>
Do all of the above and you will see “alloc” logged twice. I cannot get these two custom tasks to share the “big data”.
I am running ant 1.8.1 on Windows with these two env vars:
- JAVA_HOME=C:\Program Files\Java\jdk1.6.0_21
- CLASSPATH=(empty)
Hint: If you want to step into this custom task from an Ant (1.8) process, set your breakpoints here:
org.apache.tools.ant.launch.Launcher.main()org.apache.tools.ant.UnknownElement.execute()
The solution is simple, but poorly (or not?) documented on the Ant website. (I will commit a patch to the Ant docs to correct this situation!)
I needed to use the attribute
loaderrefontaskdefnodes. The token is used to reference the ClassLoader (and share it). After, static members are shared between custom tasks correctly.Corrected Ant build.xml:
<?xml version="1.0" encoding="UTF-8"?> <project name="MyTask" basedir="." default="init"> <target name="init" description="test the custom task" > <taskdef name="CustomTask1" classname="AntCustomTask1" classpath="C:\my_custom_ant_task_class_files" loaderref="my_shared_class_loader" /> <taskdef name="CustomTask2" classname="AntCustomTask2" classpath="C:\my_custom_ant_task_class_files" loaderref="my_shared_class_loader" /> <CustomTask1/> <CustomTask2/> </target> </project>