Code at runtime in Java 5/6

One of the great features added in Java 5 was annotations. The meta data carried by annotations can be processed by the Annotation Processing Tool (apt), to generate new classes, more code or even data files (like Hibernate mapping files and such). However, annotations can also be stored in the byte codes and reflected at runtime. This becomes a truly amazing feature when you combine it with the Proxy class that was added in Java 1.2. How so? Imagine you create an interface with a bunch of methods, annotate them with what you want them to do, and then an API can generate an implementation for you, at runtime! The really awesome part of this thing? You won’t be generating any byte codes, it’s all done for you!

This is in fact, exactly how EoD SQL works. You annotate a method with your database queries (SELECT, INSERT, UPDATE, DELETE, etc), and it generates an implementation for you with it’s QueryTool class. So, how do you do it? Its actually really really easy.

First you need your annotation class, for the purpose of example, we’ll create interfaces map to Properties files. What we’ll be writing:

  • An annotation to bind a method to a property name
  • A class that generates the implementations
  • An InvocationHandler that actually does the grunt work

First off, our annotation:

@Target(ElementType.METHOD) // only allowed to annotate methods
@Retention(RetentionPolicy.RUNTIME) // if we don't do this, your annotations will be thrown away at compile time
public @interface PropertyBound {
    public String value();
}

Isn’t it simple? Now we need the InvocationHandler which will handle the method invocations from our Proxy classes (the stubs generated by the VM to implement the requested interface):

public class PropertyInvokationHandler implements InvocationHandler {
    private Properties properties;
    public PropertyInvokationHandler(Properties properties) {
        this.properties = properties;
    }

    public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
        PropertyBound binding = method.getAnnotation(PropertyBound.class);

        if(binding != null) {
            return properties.getProperty(binding.value());
        } else {
            throw new RuntimeException("Method is not bound to a property: " + method);
        }
    }
}

Here we use the “value” method of our PropertyBound annotation to find the key of the property for that method. If no PropertyBound is found, we throw an exception. Now we need a nice class that binds interfaces to a Proxy implementation:

public class PropertyTool {
    private PropertyTool() { } // you can't instantiate this class from outside

    public static <T> T bindProperties(Class<T> clazz, Properties properties) {
        return (T)Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            new Class[] { clazz },
            new PropertyInvokationHandler(properties)
        );
    }
}

Thats all there is to it. Simple no? So how do we use this now? First you need an interface that is bound to a set of Properties:

public interface MyConfig {
    @PropertyBound("user.name")
    public String getUserName();

    @PropertyBound("user.password")
    public String getPassword();
}

This means that calling getUserName() will getProperty(“user.name”), and getPassword() will getProperty(“user.password”). Bringing it all together (finally):

public class MyConfigReader {
    public static void main(String[] args) {
        Properties properties = new Properties();
        try {
            InputStream in = new FileInputStream("test.properties");
            properties.load(in);
            in.close();
        } catch(IOException ex) {
            ex.printStackTrace();
        }

        MyConfig config = PropertyTool.bindProperties(MyConfig.class, properties);
        System.out.println("User Name: " + config.getUserName());
        System.out.println("Password: " + config.getPassword());
    }
}

Obviously there are far more useful ways you can use these classes together, but as you can see the combination can be extremely cool.

About these ads

5 Responses to “Code at runtime in Java 5/6”

  1. erka Says:

    You could make it more reusable. Something likes method with follow signature:

    public static T bindProperties(Class clazz, String propertyFileName) {
    //
    }

    The “main” could be

    public class MyConfigReader {
    public static void main(String[] args) {
    MyConfig config = PropertyTool.bindProperties(MyConfig.class, ”test.properties”);
    System.out.println(”User Name: ” + config.getUserName());
    System.out.println(”Password: ” + config.getPassword());
    }
    }

  2. Jason Says:

    I did think of doing that, and loading the Properties as a resource, but I find working either with InputStreams, or the actual object more flexible long term, since then you’re not bound by where the file actually sits. At the end of the day, you could use operator overloading to do:

    public static T bindProperties(Class clazz, String resourceName) {
    Properties props = new Properties();
    // … load the properties from a resource
    return bindProperties(clazz, props);
    }

    That way you have both. I tend to favor this approach, one method that actually does the hard work, and lots of convenience methods that just call it underneath.

  3. Dynamic Coding in Java « Techno Lemming Says:

    […] to use than code that you have to figure out what it’s doing underneath. I’ve covered faking dynamic code before, but what about really generating code at runtime? A lot of people do a quick Google and come up […]

  4. Paul Holser Says:

    Hi there,

    I wanted to let you know that this article was very inspiring. It, along with projects like JewelCLI (which use a very similar technique), led me to write an article for devx.com and flesh out the ideas you describe in an actual library, Property Binder. I’d be very interested to hear your constructive feedback!

    http://pholser.com/software/property-binder/

    • Jason Says:

      Hi Paul,

      Thanks for the great comment.

      I’ve taken a good look at property-binder, and it’s a great API. I always favour API structures that at least appear small and simple (even if they are far more complex under-the-hood).

      The smaller the mental-footprint: the better.

      Cheers,
      //Jason


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: