Chapter 10. Running Aspectized Applications

10.1. Regular Java Applications

Applications using JBoss AOP can be run standalone, or they can be run as part of the JBoss application server. When running AOP standalone, you can either use classes that have been instrumented using the AOP precompiler, or classes that have only simply compiled using javac to be instrumented by AOP when they are first loaded.

10.1.1. Precompiled instrumentation

Running a precompiled aop application is quite similar to running a normal java application. In addition to the classpath required for your application you need to specify the files required for aop:

  • javassist.jar
  • trove.jar
  • concurrent.jar
  • jboss-common.jar
  • jboss-aop.jar
  • or jboss-aop-jdk50.jar

- depending on if you are using JDK 1.4 (jboss-aop.jar) or JDK 5.0 (jboss-aop-jdk50.jar)

You need to tell JBoss AOP where the xml configuration files of your bindings are. This can be done in one of these two ways:

  • Set the jboss.aop.path system property. (You can specify multiple files or directories separated by ':' (*nix) or ';' (Windows), i.e. -Djboss.aop.path=jboss-aop.xml;metadata-aop.xml) If you specify a directory, all aop.xml files will be loaded from there as well.
  • Package your classes in a jar where /META-INF/jboss-aop.xml contains your bindings.

If you are using annotated bindings (See Chapter "Annotated Bindings"), you must tell JBoss AOP which JARS or directories that may have annotated @Aspects. To do this you must set the jboss.aop.class.path system property. (You can specify multiple jars or directories separated by ':' (*nix) or ';' (Windows), i.e. -Djboss.aop.class.path=aspects.jar;classes)

So to run a precompiled AOP application, where your jboss-aop.xml file is not part of a jar, you enter this at a command prompt:

$ java -cp=<classpath as described above> -Djboss.aop.path=<path to jboss-aop.xml> \
         -Djboss.aop.class.path=aspects.jar
         com.blah.MyMainClass
            

To run a precompiled AOP application, where your application contains a jar with a META-INF/jboss-aop.xml file, you would need to do this from the command-line:

$ java -cp=<classpath as described above> com.blah.MyMainClass
            

In the /bin folder of the distribution we have provided batch/script files to make this easier. It includes all the aop libs for you, so you just have to worry about your files. The usage for JDK 1.4 is:

$ run-precompiled classpath [-aoppath path_to_aop.xml] [-aopclasspath path_to_annotated] \
      com.blah.MyMainClass [args...]
            

For JDK 1.5:

$ run-precompiled15 classpath [-aoppath path_to_aop.xml] [-aopclasspath path_to_annotated] \
      com.blah.MyMainClass [args...]
            

If your application is not in a jar with a META-INF/jboss-aop.xml file, you must specify the path to your *-aop.xml files in the -aoppath parameter, and if your class comtains aspects configured via annotations (@Aspect etc.) you must pass in this classpath via the -aopclasspath parameter. (For JDK 1.4, you must have compiled the annotations first).

10.1.2. Loadtime

This section describes how to use loadtime instrumentation of classes with aop. The classes themselves are just compiled using Java, but are not precompiled with the aop precompiler. (For JDK 1.4, if you are using annotations, you will also need to use the annotation compiler to take advantage of the annotations.) In the examples given if your classes are contained in a jar with a META-INF/jboss-aop.xml file, you would omit the -Djboss.aop.path system property.

How to run this is quite similar to running the precompiled examples, you need to specify one more thing. In JDK 1.4, you must also set the java.system.class.loader system property to org.jboss.aop.standalone.SystemClassLoader. Here's how run an AOP application in JDK 1.4 with loadtime instrumentation, where your jboss-aop.xml file is not part of a jar:

$ java -cp=<classpath as described above> -Djboss.aop.path=<path to jboss-aop.xml> \
      -Djava.system.class.loader=org.jboss.aop.standalone.SystemClassLoader \
      com.blah.MyMainClass
            

And to run an AOP application in JDK 1.4 with loadtime instrumentation, where your application contains a jar with a META-INF/jboss-aop.xml file:

$ java -cp=<classpath as described above> \
      -Djava.system.class.loader=org.jboss.aop.standalone.SystemClassLoader \
      com.blah.MyMainClass
            

In the /bin folder of the distribution we have provided batch/script files to make

this easier. It includes all the aop libs for you, so you just have to worry about your files. The usage for JDK 1.4 is:

$ run-load-system classpath [-aoppath path_to_aop.xml] [-aopclasspath path_to_annotated] \
      com.blah.MyMainClass [args...]
            

The parameters have the same meaning as for the run-precompiled scripts. (Since this is for JDK 1.4, you must have compiled the annotations first).

JBoss AOP uses the JDK 5.0 java.lang.instrument package to enable loadtime transformations. To run loadtime transformations with JDK 5.0, you do not specify the java.system.class.loader system property. Instead you pass in the JVM command line switch javaagent with a value of -javaagent=jboss-aop-jdk50.jar. For these examples make sure that you use jboss-aop-jdk50.jar and not jboss-aop.jar in your classpath. Here's how run an AOP application in JDK 5.0 with loadtime instrumentation, where your jboss-aop.xml file is not part of a jar:

$ java -cp=<classpath as described above> -Djboss.aop.path=<path to jboss-aop.xml> \
      -javaagent:jboss-aop-jdk50.jar com.blah.MyMainClass
            

And to run an AOP application in JDK 5.0 with loadtime instrumentation, where your application contains a jar with a META-INF/jboss-aop.xml file:

$ java -cp=<classpath as described above> -javaagent:jboss-aop-jdk50.jar \
      com.blah.MyMainClass
            

In the /bin folder of the distribution we have provided batch/script files to make this easier. It includes all the aop libs for you, so you just have to worry about your files. The usage for JDK 1.5 is:

$ run-load15 classpath [-aoppath path_to_aop.xml] [-aopclasspath path_to_annotated] \
      com.blah.MyMainClass [args...]
            

The parameters have the same meaning as for the run-precompiled scripts. (Since this is for JDK 1.5, there is no need to compile the annotations first).

10.1.3. Loadtime Alternative

A better way to run loadtime transformations using JDK 1.4, which is more in line with what is done when running loadtime transformations for JDK 1.5, uses some non-standard options of Java to override java.lang.ClassLoader with a custom classloader that hooks into the library. The custom classloader must be added to the default bootstrap class path (bootclasspath) for your classes to get instrumented at loadtime. The classes used are dependent upon the VM. At present this custom classloader has only been tested for J2SE 1.4, and does NOT work with J2SE 5.0 (For 1.5 use the -javaagent switch as mentioned above. Due to licensing issues we are not allowed to ship the precompiled version of the custom classloader. The steps to compile and use the custom classloader are shown below.

As implied above, the java executable used in this example MUST be the one that ships with JDK 1.4. If you also have, say, the JDK 1.5 runtime installed, you may run into problems. To be absolutely sure, in the console you are using set the JAVA_HOME environment variable to point to the root of your JDK 1.4 installation. Then on Windows invoke java as:

$ %JAVA_HOME%\bin\java ...
            

On Unix invoke java as:

$ $JAVA_HOME/bin/java ...
            

To use this you first need to generate the classloader:

$ java -cp=<classpath as described above>  \
       org.jboss.aop.hook.GenerateInstrumentedClassLoader <output dir>
            

For the following example, the aop boot classpath should be the output dir specified above, followed by the jars needed for AOP, i.e. javassist.jar, trove.jar, concurrent.jar, jboss-common.jar and jboss-aop.jar. You separate the classpath elements as normal, with ';' (Windows) or ':' (Unix). The path to your classes should NOT be included here! You then use this aop boot classpath as the argument for -Xbootclasspath option as shown here:

$ java -Xbootclasspath/p:<aop boot classpath as described> \
      -Djboss.aop.path=<path to jboss-aop.xml> \
      -classpath <path to your classes> com.blah.MyMainClass
            

In the /bin folder of the distribution we have provided batch/script files to make this easier. It includes all the aop libs for you, so you just have to worry about your files. The usage for JDK 1.5 is:

$ run-load-boot classpath [-aoppath path_to_aop.xml] [-aopclasspath path_to_annotated] \
      com.blah.MyMainClass [args...]
            

The parameters have the same meaning as for the run-precompiled scripts. (Since this is for JDK 1.4, you must have compiled the annotations first). This script both creates the instrumented class loader and makes sure that that the JAVA_HOME environment variable has been set (Your job is to make sure it points to a 1.4 distribution!).

10.2. JBoss Application Server 4.x

JBoss AOP is integrated with JBoss 4.0 and JBoss 3.2.6RC1+ application server. You can deploy beans in two ways, precompiled for aop, or for loadtime instrumentation. The definitions of these are the same as above.

JBoss AOP comes distributed with the JBoss 4.x Application Server. It is best to download the latest version and update your JBoss Application Server installation as described in the "Installing" chapter of this guide.

To enable loadtime transformations in JBoss you need to perform the following steps:

  • Unjar deploy/jboss-aop.deployer
  • Edit META-INF/jboss-service.xml as described below
  • Rejar deploy/jboss-aop.deployer

Later versions of JBoss Application Server will be distributed with this archive exploded as a directory so you do not have to unjar.

The jboss-aop.deployer file contains some MBeans that deploy and manage the AOP framework.

      <mbean code="org.jboss.aop.deployment.AspectManagerService"
         name="jboss.aop:service=AspectManager">
         <attribute name="EnableTransformer">false</attribute>
         <!-- only relevant when EnableTransformer is true -->
         <attribute name="SuppressTransformationErrors">true</attribute>
         <!-- only relevant when Enabletransformer is true.  Optimization is optional
         only just in case there is a bug in it -->
         <attribute name="Optimized">true</attribute>
         <attribute name="Verbose">false</attribute>
      </mbean>

      <mbean code="org.jboss.aop.deployment.AspectDeployer"
         name="jboss.aop:service=AspectDeployer">
      </mbean>
    

By default, JBoss application server will not do load-time bytecode manipulation of AOP files and you will need to use the precompiler. You can turn this on by setting the EnableTransformer attribute to true. If SuppressTransformationErrors is true failed bytecode transformation will only give an error warning. This flag is needed because the JSP compiler does not run within a JBoss classloader and the AOP loader cannot resolve classes from this JSP classloader.

To deploy an AOP application in JBoss you need to package it. AOP is packaged similarly to SARs(MBeans). You can either deploy an XML file directly in the deploy/ directory with the signature *-aop.xml along with your package (this is how the base-aop.xml, included in the aop.deployer file works) or you can include it in the jar fail containing your classes. If you include your xml file in your jar, it must have the file extension .aop and a jboss-aop.xml file must be contained in a META-INF directory, i.e. META-INF/jboss-aop.xml.

If you want to create anything more than a non-trivial example, using the .aop jar files, you can make any top-level deployment contain a .aop file containing the xml binding configuration. That is you can have a .aop file in an .ear file, or a .aop file in a war file etc. The bindings specified in the META-INF/jboss-aop.xml file contained in the .aop file will affect all the classes in the whole war!

10.3. JBoss Application Server 3.2.x

JBoss AOP can also work with JBoss 3.2.6RC1+ and higher in the JBoss 3.2 series. Look in the Installing chapter on how to install the JAR files.

After installing, you need to modify the jboss-3.2.6/server/xxx/conf/jboss-service.xml file to add the mbean definitions mentioned for the 4.0 release, and copy the base-aop.xml file into the server/xxx/deploy/ directory if you want to use any of JBoss Aspects.

*NOTE*!!! JBoss 3.2.x series does not support class-load-time transformations. You MUST use the JBoss AOP precompiler if you want to run in JBoss 3.2.x.