Picocontainer Null Object Builder
Charles Miller pointed out that passing null
instead of a null object would just as happily generate an exception. I like to be explicit though, especially when cheating and purposefully not providing a component implementation. As promised in the comments, here is a much fancier null component builder (and testcase) than you'll ever really need ;-)
package org.skife.picotools;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class NC
{
private static class NCHandler implements InvocationHandler
{
private final Class iface;
NCHandler(final Class iface)
{
this.iface = iface;
}
public Object invoke(final Object proxy,
final Method method,
final Object[] args) throws Throwable
{
final StringBuffer signature = new StringBuffer();
signature.append(method.getDeclaringClass().getName()).append("#");
signature.append(method.getName()).append("(");
final Class[] params = method.getParameterTypes();
for (int i = 0; i != params.length; i++)
{
final Class param = params[i];
signature.append(param.getName());
if (i != params.length - 1) signature.append(", ");
}
signature.append("): ")
.append(method.getReturnType().getName())
.append("]");
throw new IllegalStateException(new StringBuffer()
.append("Invoked method [")
.append(signature.toString())
.append(" on null component implementing [")
.append(iface.getName())
.append("]").toString());
}
};
public static Object build(final Class iface)
{
return Proxy.newProxyInstance(iface.getClassLoader(),
new Class[]{iface},
new NCHandler(iface));
}
}
package org.skife.picotools;
import java.util.Map;
import junit.framework.TestCase;
public class NCTest extends TestCase {
public void testThing() {
final Map null_map = (Map) NC.build(Map.class);
try {
null_map.put("key", "value");
fail("Should have thrown excpetion");
} catch (IllegalStateException e) {
assertTrue("Go through here", true);
}
}
}
Exception message will look like Invoked method [java.util.Map#put(java.lang.Object, java.lang.Object): java.lang.Object] on null component implementing [java.util.Map]
Easy, and the error is much more explicit than a null pointer exception. Admittedly, (WombatDAO)NC.build(WombatDAO.class)
is 21 keystrokes more than (WombatDAO)null
but we are using Java here, not Perl =)