|
|
|
Sponsored Link •
|
Summary
The Handy-Dandy Null Object Pattern Looked at from the AOP Perspective
|
Advertisement
|
pointcut nullMemberAssignments(Object pSetValue):
set(* *.*) && args(pSetValue) &&
!within(test.NullObjectAspect) && !within(test.NullProxy);
The set joinpoint
matches all assignment statements in the code that is to be aspected. The args joinpoint matches, and binds, the value of the object being assigned. The !within joinpoint is following a typical AOP idiom -- all aspected(1) code but not the aspect (and related instrumentation).
pointcut callsThatReturnAnObject(Object pCalledObject):
call(* *.*(..)) && target(pCalledObject) &&
!within(test.NullObjectAspect) && !within(test.NullProxy);
The call joinpoint matches all method calls that return a value(2). The target joinpoint matches and binds the object of the method being invoked.
Object around(Object pCalledObject): callsThatReturnAnObject(pCalledObject)
{
...
//Is the program trying to invoke a method call on a Null Object instance?
if(cNullObjectMap.containsKey(pCalledObject))
{
NullPointerException lNpe = new NullPointerException();
...
lNpe.setStackTrace(lNewStackTrace);
lNpe.initCause((NullPointerException)cNullObjectMap.get(pCalledObject));
cNullObjectMap.remove(pCalledObject);
throw lNpe;
}
lRetVal = proceed(pCalledObject);
//Did the method return null?
if(lRetVal == null)
{
NullPointerException lE = new NullPointerException();
...
lRetVal = lErrorMethod.getReturnType().newInstance();
...
cNullObjectMap.put(lRetVal, lE);
}
...
}
Object around(Object pSetValue): nullMemberAssignments(pSetValue)
{
...
if(pSetValue == null)
{
NullPointerException lE = new NullPointerException();
...
lRetVal = lErrorField.getFieldType().newInstance();
...
cNullObjectMap.put(lRetVal, lE);
}
return proceed(lRetVal);
}
The first problem I ran into was an unexpected and unhandled NPE happening in the aspect's advice. Creating a new object using Class.newInstance() was returning a null. But why?... because the "class" was an interface! Ouch - no apparent solution. I put the project away for a couple days and was happily distracted by fatherhood. When I came back, I realized almost immediately that Java 1.3's dynamic proxy fits the problem perfectly.java.lang.NullPointerException at test.Main.main(Main.java:33) Caused by: java.lang.NullPointerException: Null return value from test.Main.nullStringTest(Main.java:32) at test.Main.main(Main.java:32) java.lang.NullPointerException at test.Main.main(Main.java:43) Caused by: java.lang.NullPointerException: Null return value from test.Main.nullArrayListTest(Main.java:42) at test.Main.main(Main.java:42) java.lang.NullPointerException at test.Main.main(Main.java:53) Caused by: java.lang.NullPointerException: Null value assigned to field test.Main.cList(Main.java:22) at test.Main.(Main.java:22) at test.Main.main(Main.java:28) java.lang.NullPointerException at test.Main.main(Main.java:63) Caused by: java.lang.NullPointerException: Null return value from test.Main.nullArrayListTest(Main.java:62) at test.Main.main(Main.java:62) Exception in thread "main"
Have an opinion? Be the first to post a comment about this weblog entry.
If you'd like to be notified whenever Dale Asberry adds a new entry to his weblog, subscribe to his RSS feed.
![]() | R. Dale Asberry been hacking since 1978, professionally since 1990. He's certified in Java 1.1 and has a four digit MCP number. He discovered Jini at the 2000 JavaOne and has been building incredibly cool, dynamic, distributed architectures ever since! Over time, he's discovered several principles that have contributed to his success - they are the Princples of: Enabling Others, Simplicity, No Complaining, Least Work, Least Surprise, Least Damage, and "It Just Works". |
|
Sponsored Links
|