tags:

views:

79

answers:

4

I'm developing a few custom ant tasks that all need to initialize the same objects. I wanted to initialize those object's in a common superclass that extends from Task, in the init() method. But I see from the lifecycle of an ant task that init() gets called before the tasks child elements and attributes are set. So all of the data I need for initializing those objects is unavailable during init(), if I am reading right.

So, why is init() called at this point? What do you even know that you could use in init()? What could it be used for?

(And is there some other method that I can rely on to be called before execute(), but after my data is available?)

+1  A: 

The init() method is called on each Task upon parsing of the build file and also after the Task has been bound to its owning project. So the Task can do work that involves a Project instance.

cherouvim
A: 

Why not perform the initialisation in a singleton and then get the ant tasks to call the singleton to get the initialsed data? Then you only pay for the initialisation once.

Michael Ransley
A: 

To get the effect of doing some initialization in the baseclass before the execute method is called you can implement execute() in the base class, create these objects, and call an abstract method declared in your base class. For example:

public abstract class BaseClass extends Task {
  public final void execute() {
    Foo foo = createFoo();
    Bar bar = createBar(foo);
    execute(foo,bar);
  }
  public abstract void execute(Foo foo, Bar bar);
}

public class BazTask extends BaseClass {
  public void execute(Foo foo, Bar bar) {
    System.out.println("foo is " + foo + " and bar is " + bar);
  }
}

You could also store the created objects as fields and give the method a different name (like executeTask) instead of overloading based on the parameters.

Geoff Reedy
+1  A: 

The best guide to this is to look at the source code of the tasks that Ant ships with. There seems to be 3 main use cases for init():

  1. Pre-initialization of delegate objects. For example, the Sync task delegates most of its work to an underlying object, passing through some of the setXYZ() to this delegate. The instantiation and pre-configuration of this delegate has to happen before any properties are set on the task.
  2. Configuration of defaults for property values, which are based on general project settings. For example, the SSH task initializes its knownHosts default by looking at a System property. Also, the Project object has been injected into the task by the init() is called, so the task can look at that.
  3. Adding of optional 3rd-party dependencies to the classpath. For example, the JUnit task adds various Junit-related dependencies. These can only be loaded when the task is used, since they're optional.

All of the above could conceivably be done inside the task constructor, but the use of an explicit init() method is in keeping with the Ant task design.

As for the second part of your question, no, there is no lifecycle hook that gets called between the properties being set, and execute() being called. You have to do that inside execute() itself.

skaffman