javaxmlantsingletontaskdef

How to have one instance of a singleton class throughout the execution of ant taskdef actions


I have a build.xml file which have taskdef actions to invoke java classes. In the code attached below i am invoking two different java classes HelloWorld.java and HelloWorld1.java with taskdef actions in build.xml.

I have defined a singleton class along with the two classes and i am invoking this singleton class ClassicSingleton.java from both the above mentioned java files. While trying to print the instances of the singleton class which i am getting from the singleton class i could see that different new instances are created for the java classes invoked from different taskdef actions but i need to use same singleton instance for all the java classes. One thing to be noted is i am getting the same instance when i am invoking getInstance() method in ClassicSingleton class twice from the same HelloWorld.java class.

Please help me if there is any way to use the same instance of the singleton class for all the taskdef actions. Attaching my code below.

build.xml

    <property name="build.dir" value="${basedir}/build" />
    <property name="lib.dir" value="${basedir}/lib" />
    <property name="release.dir" value="${basedir}/release"/>
    <property name="base.dir" value="E://install/" />


    <target name="runclasses" description="Use the Task">
        <taskdef name="helloworld" classname="HelloWorld" classpath="HelloWorld.jar"/>
        <helloworld/>
        <taskdef name="helloworld1" classname="HelloWorld1" classpath="HelloWorld.jar"/>
        <helloworld1/>
    </target>

    <target name="makejar">
        <jar destfile="${base.dir}/HelloWorld.jar"
       basedir="${build.dir}" includes="**/*.class" />
    </target>

    <target name="release" depends="makejar,runclasses"/>
</project>

HelloWorld.java

import java.util.Map;
import java.util.Set;
import java.util.Iterator;

public class HelloWorld {
    public void execute() {
        System.out.println("came to Hello World");
        ClassicSingleton instance = ClassicSingleton.getInstance();
        Map<String,String> mymap = instance.getProperties("E://install/build.properties");
        Object value = mymap.get("$AUTH_DB_USER$");
        System.out.println(value);
        System.out.println(instance);
        mymap.put("$AUTH_DB_USER$","sample");
        Object val = mymap.get("$AUTH_DB_USER$");
        System.out.println(val);
        instance = ClassicSingleton.getInstance();
        mymap = instance.getProperties("E://install/build.properties");
        value = mymap.get("$AUTH_DB_USER$");
        System.out.println(value);
        System.out.println(instance);
    }
}

HelloWorld1.java

import java.util.Map;
public class HelloWorld1 {
    public void execute(){
        System.out.println("hai HelloWorld1");
        ClassicSingleton instance = ClassicSingleton.getInstance();
        Map<String,String> mymap = instance.getProperties("E://install/build.properties");
        System.out.println("came to HelloWorld1");
        Object value = mymap.get("$AUTH_DB_USER$");
        System.out.println(value);
        System.out.println(instance);
    }
}

ClassicSingleton.java

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

public class ClassicSingleton {
   private static ClassicSingleton instance = null;
   protected ClassicSingleton() {
      // Exists only to defeat instantiation.
   }
   public synchronized static ClassicSingleton getInstance() {
      if(instance == null) {
         instance = new ClassicSingleton();
      }
      return instance;
   }

   private static final Map<String,String> propertiesMap = new HashMap<String,String>();
    public static Map<String,String> getProperties(String propertiesFilePath){
        try {
            File file = new File(propertiesFilePath);
            FileInputStream fileInput = new FileInputStream(file);
            Properties properties = new Properties();
            properties.load(fileInput);
            fileInput.close();
            Set<Object> keys = properties.keySet();
            Iterator<Object> iterator = keys.iterator();
            while (iterator.hasNext()) {
                String string = (String)iterator.next();
                StringBuilder key = new StringBuilder("$"+string+"$");
                String value = properties.getProperty(string);
                propertiesMap.put(key.toString(), value);
            }
        } catch (Exception exception) {
            System.out.println("Exception came");
        }
        return propertiesMap;
    }
}

Output when i executed the build.xml
Output when i executed the build.xml


Solution

  • You have to share class loader for both of your tasks, otherwise tasks will be loaded in two different and independant classloader and thus you will get two different instance of your singleton (one for each classloader). To achieve this, you can supply a loaderref attribute to your task definition (see Typedef task):

    <path id="lib.path">
      <fileset dir="${base.dir}" includes="HelloWord.jar"/>
    </path>
    
    <target name="runclasses" description="Use the Task">
        <taskdef name="helloworld" classname="HelloWorld" classpathref="lib.path" loaderref="lib.path.loader"/>
        <helloworld/>
        <taskdef name="helloworld1" classname="HelloWorld1" classpathref="lib.path" loaderref="lib.path.loader"/>
        <helloworld1/>
    </target>