Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Author: jboner jboner

Introduction

In the previous tutorial we learned how to write, define, weave in and run an aspect. So if you have not read it yet, please do that first.

We also learned how to write and use before and after advice, which allowed us to define code blocks that does something before and after a specific action is triggered.

In this tutorial we will learn how to make use of one of the most powerful constructs in AOP; the around advice. We will implement a little around advice that hijacks the HelloWorld.greet() to make the traditional greeting a bit more interesting.

The Test Application

Here is the same old Hello World application.

Code Block
java
java
package testAOP;

public class HelloWorld {

     public static void main(String args[]) {
         HelloWorld world = new HelloWorld();
         System.out.println(world.greet());
     }

     public String greet() {
         return "Hello World!";
     }
}

It is a standard Java application and can be compiled with javac -d target HelloWorld.java.

However this application is indeed a bit boring and we are all pretty tired of it. So let's try to make it a bit more interesting, let's hijack the HelloWorld.greet() method.

Writing and defining the Aspect

To be able to hijack the greet() method we need to make use of the around advice construct.

The around advice can be seen as being invoked "around" or "instead of" the the actual method invocation (can be any well-defined action, aka join point), "intercepting" the invocation. Basically it allows us to replace the regular code and define our own code that runs instead of the regular code.

But the key point is that we also have the "magic" method proceed() which allows us to proceed with the invocation and trigger the action that we have just replaced.
Follow?

Let's take a look at some code to make less abstract:

Code Block
java
java
package testAOP;

import org.codehaus.aspectwerkz.joinpoint.JoinPoint;

public class HelloWorldHijacker {

  /**
    * @Around execution(* testAOP.HelloWorld.greet(..))
    */
    public Object yellifyier(JoinPoint joinPoint) {
        Object greeting = joinPoint.proceed();
        return "<yell>" + greeting + "</yell>";
    }
}

In this code we have an advice method called yellifyier, which we define (using annotations) as being an around advice. What this method does is first invoke the original greet() method (which we have intercepted using the yellifyier around advice) using the "magic" method JoinPoint.proceed(). This method returns the result from the original method invocation. In this case the "Hello World!" string. So what we then do is making the Hello World application yell the greeting. (Well don't know if it was that much more fun.)

In the Around annotation we also bind the advice to a specific join point, in this case an anonymous one that picks out the HelloWorld.greet() method.

For more information about the annotation and XML definition, pointcut patterns etc. see the online documentation.

We also have to provide a tiny XML deployment descriptor (in this example called aop.xml) to tell the AspectWerkz system which Java classes it should treat and load as aspects:

Code Block
<aspectwerkz>
    <system id="AspectWerkzExample">
        <aspect class="testAOP.HelloWorldHijacker"/>
    </system>
</aspectwerkz>

Weaving and running the Aspect

After adding annotations you need to run a special AspectWerkz tool. This is done after compiling your aspect class files, (i.e. after running javac). The tool, known as the AspectC compiler, can be invoked as follows, passing in the source directory (.), and the class directory (target):

Code Block
java -cp $ASPECTWERKZ_HOME/lib/aspectwerkz-0.10.jar:$ASPECTWERKZ_HOME/lib/bcel.jar org.codehaus.aspectwerkz.definition.AspectC . target

More information on the AspectC compiler can be found here.

Now we are ready to run the weave in our aspect and run the Hello World application. This is done using the aspectwerkz command line tool:

Code Block
$ASPECTWERKZ_HOME/bin/aspectwerkz -Daspectwerkz.definition.file=aop.xml -cp target testAOP.HelloWorld

See the previous Hello World tutorial on the online documentation for details.

This produces the expected output:

Code Block
<yell>Hello World!</yell>

and as you can see, the greeting is now yelled out.

Conclusion

The key points I am trying to illustrate here is that:

  1. the HelloWorld application is completely oblivious of the fact that it is actually yelling out the greeting
  2. the yellifier advice implementation is generic and can be used to yell out output captured from any method (that does not return void).

However, you might have noticed that the definition (in the aspect annotation) is not generic but coupled to the HelloWorld application. We can easily loosen up this strong coupling and make the aspect completely reusable. For more information about that, read the next tutorial.