Reducing Upgrade Risk with Aspect Oriented Programming
Pages: 1, 2
Upgrading the Observer "Listener" via AOP
Once we've intercepted the getNewData() method, its
return data can be augmented by a call into a JNDI naming service. The
call searches for a file named report.txt. This data is
then returned to the caller--NMSListener.update().
public class UpgradeInterceptor implements Interceptor
{
public Object intercept(Invocation invocation)
throws Throwable
{
String methodName = getFullMethodName(invocation);
System.out.println("Intercepted method name: " + methodName);
// Call the intercepted method.
Object result = invocation.proceed();
// Now call into JNDI to get some data
Lookup aLookup = new Lookup();
// Add this data to the intercepted method result
return (String) result + aLookup.directoryLookup("report.txt");
}
}
The Lookup class retrieves the required object
(report.txt) from the naming service using the following
code:
// Create the initial context
Context ctx = new InitialContext(env);
// Look up an object
Object obj = ctx.lookup(searchElement);
The object is then returned to the intercept method.
Executing the Program
The code was written using Java Standard Edition version 1.5.0_01. The following four AOP-related .jar files are required and have to be placed in the classpath:
bsh-2.0b1.jarcglib-asm-1.0.jardynaop-1.0-beta.jarjakarta-oro-2.0.7.jar
These can be downloaded from the dynaop project's Documents and Files page.
They're included in a single .zip file called dynaop-1.0-beta.zip.
Remember to place the script file (mentioned at the start of
the article) in the same folder as the source code. You'll also have to
install JNDI and copy the file report.txt into the root
(e.g., D:\). Then compile these with the other Java files
and execute the program with the command:
java ObserverTest
This should generate the following output:
Intercepted method name: NMSSubject.getNewData()
Updated subject data is Data Set: E:\report.txt
Elapsed time in seconds 2
The first line indicates the interception and call into the upgrade code. The second line indicates the augmented data. The third line illustrates the time taken to run the program--an uninstrumented version of the program has an elapsed time of zero! This overhead is a downside to using the AOP technique.
Upgrading via AOP
We've now seen all of the elements required to implement an AOP-borne
upgrade. For the example above, I added the upgrade code in the
UpgradeInterceptor class. Let's say we had an
operational system that we wanted to upgrade (perhaps some serious bug
had just been discovered). Let's assume that the
ObserverTest class in the field has no AOP
instrumentation.
To upgrade the ObserverTest class, we have to copy the
following files:
- Copy the compiled AOP-instrumented
ObserverTestclass .
- Copy the
dynaopscript file dynaop.bsh.
The next time the ObserverTest class is
instantiated, it will use interception, thereby facilitating the
upgrade.
|
Related Reading
AspectJ Cookbook |
Caveat
Once the ObserverTest class has been upgraded in this
fashion, the fielded code no longer matches the compiled version--a potentially confusing state. A full release would be
advisable at some convenient time to re-align the source with the
released code. This technique should be used only in exceptional
circumstances--if at all! Also, there is a potentially
substantial time penalty incurred during the interception process.
Conclusion
Most successful software applications tend to suffer from feature creep--adding more code as each release unfolds. Some organizations still celebrate the number of lines of code their indefatigable programmers add as the product matures! Traditionally, this is sometimes referred to as "vertical development"--the software grows like an ever-expanding skyscraper.
A major benefit of AOP is that it allows for horizontal (rather than vertical) integration of new features. This powerful model facilitates a healthy degree of separation between legacy code and new features. Beyond this, AOP is an instrumentation technique that allows interfaces to be updated by intercepting code. This provides a useful mechanism for upgrading code as part of a minor or patch release. If the code has adhered to design principles such as separation of concerns, then the interception can be very effective at reducing risk. In this example, that separation was achieved with the Observer pattern, which provides a clear separation between data publishers and subscribers.
Resources
- Sample code for this article
- The
dynaopproject - Network Management, MIBs & MPLS: Principles, Design & Implementation by Stephen Morris
Stephen B. Morris is an independent writer/consultant based in Ireland.
Return to ONJava.com.