Skip to end of metadata
Go to start of metadata

Authors: David Maddison, jboner jboner

Introduction

This tutorial does not explain AOP, so if your new to the idea of AOP then please check out JavaWorld's series of articles to get you started.

What this tutorial will do is to try to walk you through a simple example on how you can write, define and weave in an aspect into your application.

Installation

Download the latest release and unzip it into the relevant location. This tutorial is based on the 2.0 version of AspectWerkz but works equally with 1.0 final.

The latest distribution can be found here.

After installation you need to set the ASPECTWERKZ_HOME environment variable to point to the installation directory. This is because quite a few of the scripts use this to find the required libraries. How this variable is set depends on you OS. Since I'm using Linux I've amended my .bashrc file, windows users could do this by using the control panel.

The Test Application

Now we've installed aspectwerkz, we need a test application into which to weave our aspects. As is the tradition, I'm going to use the standard HelloWorld application.

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

Writing the Aspect

Next we need to develop the aspect which will contain the code to be weaved into our HelloWorld class. In this example I'm going to output a statement before and after the greet method is called.

Notice the signature of the aspect methods. They need to take this JoinPoint argument otherwise the AspectWerkz weaver won't be able to identify the method when the aspect is weaved in, (and can leave you scratching your head as to why the weaving isn't working!).
(Note: for 2.0, specific optimizations can be applied by using the StaticJoinPoint interface or no interface at all. Please refer to the AspectWerkz 2.0 documentation)

To compile this aspect class you'll need to include the aspectwerkz-0.10.jar in the classpath, i.e.

For AspectWerkz 1.0 final:

Defining the Aspect

At this point we have the test application and the actual aspect code, but we still need to tell AspectWerkz where to insert the aspect methods (pointcuts), and which aspect method to actual insert (advice).

Specifying pointcuts and advice can be done using either of (or a mixture of), the following methods.

Using an XML definition file

The XML definition file is just that, an XML file which specifies the pointcuts and advice using XML syntax. Here's one that will weave our MyAspect class into our HelloWorld program (aop.xml):

Most of this should be pretty straight forward, the main part being the aspect tag. Whilst I'm not going to explain every bit of this definition file, (I'll leave that up to the official documentation), I will explain a few important points.

When specifying the pointcut the name can be any label you like, it's only used to bind the advice. The expression should be any valid expression occording to the Join point selection pattern language however you MUST make sure that the full package+class name is included in the pattern. If this isn't done, or if the pattern is slightly wrong, AspectWerkz won't be able to correctly identify the greet method.

In the advice tag, the name attribute should be the name of the method in the aspect class, (specified in the aspect tag), which you wish to insert at the specific joinpoint. Type is set to before, after, or around, depending on where exactly you wish to inser the method in relation to the joinpoint. bind-to specifies the name of the pointcut to which this advice will be bound.

This example identifies the HelloWorld.greet() method and assigns it the pointcut label greetMethod. It then inserts the MyAspect.beforeGreeting method just before greet is called, and MyAspect.afterGreeting just after the greet method returns.

Using Annotations

Annotations provide a way to add metadata to the actual aspect class, rather than specifying it in a seperate definition file. Aspect annotations are defined using JavaDoc style comments a complete list of which is available here. Using annotations, our aspect class would look as follows:

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 AnnotationC compiler, can be invoked as follows, passing in the source directory (.), and the class directory (target):

For AspectWerkz 1.0 final:

More information on the AnnotationC compiler can be found here.

Although using annotations means you don't have to write all aspect details in XML, you do still have to create a tiny XML 'stub' which tells the AspectWerkz runtime system which Java classes it should load and treat as aspects. An example of this is show below:

Weaving in and running the Aspect

There are basically two ways to actually weave the code together, one called online weaving performs the weaving as the classes are loaded into the JVM. The other is offline weaving, and is done before the code is actually run.

Using online weaving

When using online weaving you need to decide which JVM your going to use. This is because the hook which allows AspectWerkz to weave the classes together on the fly, is different in Sun HotSpot (where JDI/HotSwap is used), as apposed to BEA JRockit (where a PreProcessor is used). The default is setup to use Sun JDK 1.4.2, however if you want to use JRockit, simply edit the bin/aspectwerkz file (aspectwerkz.bat on windows), locate the "Sample Usage for JRockit" line and uncomment the command. Of course, remember to comment out the existing Java command above it.

Using JRockit is the preferred choice since it will not only perform much better (no need to run in debug mode, which using HotSwap, e.g. Sun and IBM, requires) and be more stable, but will also work on JDK 1.3, 1.4 and 1.5.

Performing the weaving is then just a matter of using the aspectwerkz command line tool to run java with the relevant classes, pointing it to the definition file, (even if using annotations you still need the 'stub' definition file), i.e.

This produces the expected output:

Using offline weaving

With offline weaving, the test applications classes are modified on the disk with the aspect calls. That is to say offline weaving amends your actual class definition, (as opposed to online weaving which doesn't modify any classes). To perform offline weaving, you use the aspectwerkz command line tool with the -offline option, as follows:

The last option on the command (target) tells AspectWerkz where your classfiles are and is very important that you type in correctly, else nothing will get weaved into your target classes and you will wonder why nothing is happening.

Running the aspect is then just a matter of invoking your main class, although you still need some of the AspectWerkz jar's on your classpath, and you still need to provide an XML definition file:

For AspectWerkz 1.0 final:

Note: Windows users need to replace the ":" path separator by a ";"

This produces the expected output:

Conclusion

Now we have learned how to:

  1. write a simple aspect in pure Java
  2. define the aspect using annotations and XML
  3. weave the aspect into your application using online and offline mode
  4. run it

Want more?

Then read the next tutorial Hijacking Hello World or the online documentation

Want to use AOP in your appplication server?

Then start by reading this dev2dev article on how to enable AOP in WebLogic Server (the concepts are generic an works for any application server).

Credits

This tutorial is based on a tutorial written by David Maddison (with modifications and enhancements by jboner jboner)

  • No labels

16 Comments

  1. Jonas,

    I may be missing something very obvious, but why is it necessary to use the 'directory' name at the end of the offline weaving command? While trying out a slightly modified version of your non-annotated example, I find that if I run the $ASPECTWERKZ_HOME/bin/aspectwerkz command twice to weave into (a) my application program (e.g. HelloWorld in this example) and then (b) into the Aspect Code (e.g. MyAspect in this example), the before and after advices do not seem to work. However, if I supply the directory name under which the aforementioned two files exist, then the advices works as expected. Is this a correct observation? Is there any other way to deal with it?

    Nirmalya

  2. The last directory in the offline command line is the dir where the classes you want to weave resides. This is different from the classpath dir(s), since those will not be weaved only used as lib. You must always provide this dir where you want your recursive weaving to start, '.' is just fine as well.

    /Jonas

  3. Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/aspectwerkz/definition/AspectC

    what's the matter, when i do the last line?

  4. Hi Jonas and Alexandre,

    I'm trying to do your HelloWorld example and the output is slightly different from the output I expected :
    ===
    before greeting...
    after greeting...
    Hello World!
    ===
    Could you explain why I can't have the expected order for the messages.
    Here are some informations about the JVM :
    java version "1.4.1_04"
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_04-b01)
    Java HotSpot(TM) Client VM (build 1.4.1_04-b01, mixed mode)
    I'm using version 2.0-RC1 of AspectWerkz.
    Hope it helps, but if you need more informations, let me know

    Thanks in advance for your help
    Ticker

  5. Jonas and Alexandre,

    I found the mistake I did : I was using the file HelloWorld.java from the second tutorial instead of the first :S
    I apologize for this pollution

    Ticker

  6. Anonymous

    A minor issue: after copy&pasting the hello world example, the compiler (rightfully) complains that greet() does not return a String.

    public String greet()

    Unknown macro: { System.out.println("Hello World!"); }
  7. $ASPECTWERKZ_HOME is set to C:\Program Files\Aspectwerkz\aspectwerkz-2.0.RC1.

    The HelloWorld.java MyAspect.java and aop.xml files are in $ASPECTWERKZ_HOME, and the HelloWorld.class and MyAspect.class files are in $ASPECTWERKZ_HOME/testAOP.

    However, when I attempt to weave offline, I continuously get the error: "The system cannot find the path specified." What is the correct syntax for the weave?

  8. Syntax fine. Problem was with my JAVA_HOME environment variable being set to:
    "C:\j2sdk1.4.2_02\bin"

    Line #14 in aspectwerkz.bat sets the JAVA_COMMAND variable (if none exists) to:
    "%JAVA_HOME%\bin\java"

    Which then equals:
    "C:\j2sdk1.4.2_02\bin\bin\java"

    Which produced the error. This would not have been a problem, if I'd already had a need to have the JAVA_COMMAND variable. However, Aspectwerkz needs the variable, and line #14 sets it (incorrectly, in this case) automatically if it doesn't exist. Correcting JAVA_HOME only compounds the problem unless you delete JAVA_COMMAND first, before running the program again.

    To remove the JAVA_COMMAND variable, enter the following command (w/no value):
    set JAVA_COMMAND=

    Looking forward to playing with this some more!

  9. There is a minor typo in the HelloWorld class:

    public String greet()

    Unknown macro: { System.out.println("Hello World!"); }

    should be:

    public void greet()

  10. The arguments to ...AnnotationC must specify the -src and -classes options:

    java org.codehaus.aspectwerkz.annotation.AnnotationC -src . -classes target

  11. Anonymous

    Hi Jonas and Alexandre,
    I can't understand clearly according to your tutorial .The jboss tutorial is very good,But jboss aop doesn't support well on standalone aop.I use your AspectWerkz,but I fail to execute successfully on the simple sample HelloWorld.I feel very ??,do you think so?May be doesn't test your example code:
    package testAOP;

    public class HelloWorld {

    public static void main(String args[])

    Unknown macro: { HelloWorld world = new HelloWorld(); world.greet(); }

    public String greet()

    Unknown macro: { System.out.println("Hello World!"); }

    }

    greet() must return a String,How do you commit such code on the tutorial.??????????

  12. Anonymous

    package testAOP;

    public class HelloWorld {

    public static void main(String args[])

    Unknown macro: { HelloWorld world = new HelloWorld(); world.greet(); }

    public String greet()

    Unknown macro: { System.out.println("Hello World!"); }

    }

    ist NOT compilable

  13. Anonymous

    Hi , this is anil , I have been using the jdk1.3.1 as the jdk version and tried to process out the HelloWorld example i.e given by you and found the error while executing the program the below error was generated when it was executed:

    %ASPECTWERKZ_HOME%/bin/aspectwerkz -Daspectwerkz.de
    finition.file=aop.xml -cp . HelloWorld
    HotSwap not supported by this java version, using bootclasspath: ._boot
    D:\jdk1.3.1_15\jre\bin\java -Xbootclasspath/p:"._boot;D:\anil\aw_2_0_2\lib\aspe
    ctwerkz-core-2.0.RC2.jar" -Daspectwerkz.home="D:\anil\aw_2_0_2" -Daspectwerkz.de
    finition.file=aop.xml -cp ".;D:\anil\aw_2_0_2\bin;;D:\anil\aw_2_0_2\lib\aspectw
    erkz-extensions-2.0.RC2.jar;D:\anil\aw_2_0_2\lib\aspectwerkz-2.0.RC2.jar;D:\anil
    \aw_2_0_2\lib\aspectwerkz-jdk14-2.0.RC2.jar;D:\anil\aw_2_0_2\lib\dom4j-1.4.jar;D
    :\anil\aw_2_0_2\lib\qdox-1.4.jar;D:\anil\aw_2_0_2\lib\concurrent-1.3.1.jar;D:\an
    il\aw_2_0_2\lib\trove-1.0.2.jar;D:\anil\aw_2_0_2\lib\jrexx-1.1.1.jar;." HelloWor
    ld
    AspectWerkz - INFO - Pre-processor org.codehaus.aspectwerkz.transform.AspectWerk
    zPreProcessor loaded and initialized
    java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/HelloWorld)
    at java.lang.ClassLoader.defineClass0(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:488)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:10
    6)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:243)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:51)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:190)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:183)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:294)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:288)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:310)
    Exception in thread "main"

    please Rectify

  14. Anonymous

    Is your version 2.0 broken? I continuously get this NoClassDefFoundError ??? Any ideas why? Please let me know....the error is posted below and so is the command I am using, my paths are right and everything, p.s., I am using the sun jdk that comes with BEA. - This of course is when I try and run this online....

    C:\>C:\DownloadedTools\aspectwerkz-2.0\bin\aspectwerkz.bat -Daspectwerkz.definit
    ion.file=C:\Workspaces\Edmunds_EAR_Workspace\JUnitFramework\aop.xml -cp target "
    C:\Workspaces\Edmunds_EAR_Workspace\JUnitFramework\testAOP\HelloWorld"
    c:\bea\jdk142_05\jre\bin\java -Xrunjdwp:transport=dt_socket,suspend=y,address=93
    00,server=y -Xdebug -Xbootclasspath/p:"C:\DownloadedTools\aspectwerkz-2.0\lib\as
    pectwerkz-core-2.0.jar" -Daspectwerkz.home="C:\DownloadedTools\aspectwerkz-2.0"
    -Daspectwerkz.definition.file=C:\Workspaces\Edmunds_EAR_Workspace\JUnitFramework
    \aop.xml -cp "C:\Program Files\Altova\xmlspy\XMLSpyInterface.jar;C:\DownloadedT
    ools\aspectwerkz-2.0\lib\aspectwerkz-extensions-2.0.jar;C:\DownloadedTools\aspec
    twerkz-2.0\lib\aspectwerkz-2.0.jar;C:\DownloadedTools\aspectwerkz-2.0\lib\aspect
    werkz-jdk14-2.0.jar;C:\DownloadedTools\aspectwerkz-2.0\lib\dom4j-1.4.jar;C:\Down
    loadedTools\aspectwerkz-2.0\lib\qdox-1.4.jar;C:\DownloadedTools\aspectwerkz-2.0\
    lib\concurrent-1.3.1.jar;C:\DownloadedTools\aspectwerkz-2.0\lib\trove-1.0.2.jar;
    C:\DownloadedTools\aspectwerkz-2.0\lib\jrexx-1.1.1.jar;target" C:\Workspaces\Edm
    unds_EAR_Workspace\JUnitFramework\testAOP\HelloWorld
    java.lang.NoClassDefFoundError: C:\Workspaces\Edmunds_EAR_Workspace\JUnitFramewo
    rk\testAOP\HelloWorld
    Exception in thread "main"

  15. Anonymous

    I´m having the same problem, while trying to use offline weaving (java -cp $ASPECTWERKZ_HOME/lib/aspectwerkz-2.0.jar;target -Daspectwerkz.definition.file=aop.xml testAOP.HelloWorld):

    Exception in thread "main" java.lang.NoClassDefFoundError: testAOP/HelloWorld

    I´m using Aspectwerkz-2.0. 

    Please, anyone help me. My e-mail is dmerlimorais@gmail.com

     Thanks a lot.

  16. Anonymous

    Hi Boner,

       How about trying to solve the problem above, reported by Merli?  It is a big problem when someone try to learn something new and the basic tutorial is wrong, is not it???? (sad)

    regards,

    Fabio