Saturday, August 16, 2008

Blind spot in the Java API: dynamic proxies

Reflecting on the good ol' days

Back in the days that the reflection API was added to Java, it meant there was a new way to do much of the same, yet in a very generic and nifty way. That came of course at a price: it slowed things down considerably - which was significant as the performance of Java as a whole (language + platform) was still quite an issue at the time.

In those days I was still working in the Telecom industries, where Java just began to get some foothold. Most of the applications running on the network nodes were still written in C++ (or even plain C) and were simply faster. The powers-that-be decided against the use of reflection (at least in production code) for exactly those performance related reasons and therefore my attention - after a short first impression - shifted away from that API.

Back to the present

Last week at work I came across some code a co-worker had written and which I was about to use for 'inspiration'. One class implemented some interface named InvocationHandler which I'd never seen before and (obviously) used reflection. I looked it up in the Sun Javadocs and found to my surprise that this interface (along with its partner in crime, the class Proxy) have been around since Java 1.3! That means over eight years - Ouch!

Ever since I read Scott Meyers books on C++ (yes, this one in particular) I know there is great advantage in being aware of the available libraries. And even though Scott's remark only seemed to apply to the standard library for C++, I'm sure he meant this in a much wider context. Any engineer should know his tools.

Knowing all of Java's APIs is another thing altogether, though. The list of classes and interfaces available in the Standard Edition alone seems to be endless, and adding the Enterprise Edition and Micro Edition to the mix makes for a sheer impossible task. I can't imagine there's a soul alive who actually does know about all of them - and knows how to use them in a practical manner, of course.

It has never been my goal to learn all about the Java APIs, just the parts that I need to write efficient code. But this is one I definetely missed...

So what's it all about then?

First off, it's called 'proxy' because it allows you to implement the Proxy design pattern (actually it's not hard to pull off a Decorator implementation either), and it's called 'dynamic' because it implements a given interface at runtime - and that's where reflection comes into play.

This is the 'classic' Proxy pattern:
Proxy patternA dynamic proxy doesn't have the compile time relationship with the interface. As said, this relationship is forged at runtime. The code for such a class might look something like this:
package server;

import java.lang.reflect.*;

public class DynamicProxy implements InvocationHandler {
    private Object realSubject;

    public DynamicProxy(Object realSubject) {
        this.realSubject = realSubject;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
        System.out.println("Before the call...");
        Object result = method.invoke(realSubject, args);
        System.out.println("...after the call.");
        return result;
    }
}
Of course you may want to insert something more useful before and after the method invocation in a practical case...

Now all one needs is the means to let the client get a reference to a Subject in a way that doesn't reveal the dynamic proxy. A factory, which normally may just hide the implementation class and/or static proxy from the client, could be 'upgraded' to do just that:
package server;

import java.lang.reflect.Proxy;

public class SubjectFactory {
    public static Subject getSubjectInstance() {
        return (Subject) Proxy.newProxyInstance(RealSubject.class
            .getClassLoader(), new Class[] { Subject.class },
            new DynamicProxy(new RealSubject()));
    }
}
Notice how:
  • the classloader of the implementation class is given as the first argument
  • the Subject interface is entered as the second parameter; in fact all (distinct) interfaces implemented by the implementation class may be given here, so RealSubject.class.getInterfaces() would be fine too
  • the DynamicProxy is instantiated given a RealSubject instance; this is the instance on which the actual invocation is performed

And this is what the class diagram has become:
Dynamic Proxy with Factory
The definitions of the Client and ServerImpl classes and Server interface haven't changed at all if a factory was used in the first place. So this little mechanism can be used to insert any pre- and post-processing you need at any time, e.g. to surround the call with session or transaction management.

Now do I hear someone say AOP? This construct actually predates AspectJ, and I guess that if you don't need all of the versatility of such a framework, it's good to know this tool is in your standard toolkit!

If this short intro has grabbed your interest, you may want to go on reading this old Javaworld article about dynamic proxies to get your feet wet a little more...