Delicious

Dynamic Loading using Java Reflection and Properties.

What is Java Reflection and Properties

In this article I will be explaining how you load classes dynamically using a properties file and Java Reflections. The Properties file are basically a collection of key-value pairs. It is the most commonly used mechanism for storing applications configuration data and settings. Reflection is a feature available in Java used by developers for examining and modifying the run-time behavior of applications running in the JVM.

MyBirds example

Let us start with a very simple problem statement: I should be able to load characters of a particular bird when I specify it's name. For e.g: When i specify duck, the calling the sound() function should print "quack";

This is a situation where you need to load a class dynamically based on some data provided by the client or external source. You also want the flexibility to configure classes in a simple properties file and these classes are having similar behavior.

To implement this we will need the following components:

Let us look at the code for each of these. Let us start with mybirds.properties.

#BIRD-TYPE=IMPLEMENTATION-CLASS
duck=com.foo.Duck
eagle=com.foo.Eagle

Now MyBird.java interface that declares the methods that the sub-classes should implement.

package com.foo;

/**
 * http://www.janeve.me
 */
public interface MyBird {
    public String sound();
}

Now let us see Duck.java and Eagle.java.

package com.foo;

/**
 * http://www.janeve.me
 */
public class Duck implements MyBird {

    public String sound() {
        return "Quack";
    }
}

 

package com.foo;

/**
 * http://www.janeve.me
 */
public class Eagle implements MyBird {

    public String sound() {
        return "Scream";
    }

}

MyBirdFactory.java is the class responsible for creating the desirable instance based on the birdType input passed to it.

package com.foo;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * http://www.janeve.me
 */
public class MyBirdFactory {

    private static final String MY_BIRDS_CONFIGURATION = "mybirds";
    private static Hashtable<String, String> myBirdsMappings = new Hashtable<String, String>();

    static {
        try {
            loadMyBirdsrMappings();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static MyBird getMyBird(String birdType) {
        String className = myBirdsMappings.get(birdType);

        MyBird bird = null;

        try {
            if( className!=null) {
                Class cls = Class.forName(className);
                bird = (MyBird)cls.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bird;
    }

    private static void loadMyBirdsrMappings() {
        ResourceBundle rb = ResourceBundle.getBundle(MY_BIRDS_CONFIGURATION, Locale.getDefault());
        for (Enumeration e = rb.getKeys(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            myBirdsMappings.put(key, rb.getString(key));
        }
    }
}

Make sure that the value of MY_BIRDS_CONFIGURATION is same as the name of the properties file.

We can write TestCode.java to test the code.

package com.foo;

/**
 * http://www.janeve.me
 */
public class TestCode {

    public static void main(String[] args) {
        if(args.length <=0)
            System.out.println("Please provide input. E.G: duck eagle duck ...");
        else {
            for(String name:args){
                MyBird bird = MyBirdFactory.getMyBird( name );
                if(bird == null){
                    System.out.println("Couldn't find your bird. Please make sure it's entered in mybirds.properties");
                } else {
                    System.out.println("The sound of the bird"  + name + " is " + bird.sound() );
                }

            }
        }

    }

}

Check out the output when you run the code.

C:\Janeve\MyBirds>java -classpath ./ com.foo.TestCode duck duck eagle duck eagle eagle
The sound of the bird duck is Quack
The sound of the bird duck is Quack
The sound of the bird eagle is Scream
The sound of the bird duck is Quack
The sound of the bird eagle is Scream
The sound of the bird eagle is Scream

C:\Janeve\MyBirds>

As you can see, the classes were loaded as per your input.You may download the complete source code.

Try adding your favorite bird in the properties file and let me know how it went.


Delicious