Annotations are only available in JDK 1.5, but using our annotation compiler you can acheive similar functionality with JDK 1.4.2.
Annotations must map to an annotation type, in JDK 1.5 they are defined as:
package com.mypackage; public @interface MyAnnotation { String myString(); int myInteger(); }
Annotation types for use with the annotation compiler are defined in exactly the same way for JDK 1.4.2, with the important difference that '@interface' is replaced by 'interface'. i.e. the simulater annotation type is a normal Java interface:
package com.mypackage; public interface MyAnnotation { String myString(); int myInteger(); }
The syntax for using annotations in JDK 1.4.2 is almost exactly the same as JDK 1.5 annotations except for these subtle differences:
This example shows an annotated class in JDK 1.4.2:
package com.mypackage; /** * @@com.mypackage.MyAnnotation (myString="class", myInteger=5) */ public class MyClass { /** * @@com.mypackage.MyAnnotation (myString="field", myInteger=4) */ private String myField; /** * @@com.mypackage.MyAnnotation (myString="constructor", myInteger=3) */ public MyClass() { } /** * @@com.mypackage.MyAnnotation (myString="method", myInteger=3) */ public int myMethod() { } }
Another JDK 1.5 feature that JBoss AOP helps introduce to JBoss 1.4.2 are Enums. As an example we can look at the org.jboss.aop.advice.Scope enum that is used for the @Aspect annotation. Here is the JDK 1.5 version.
package org.jboss.aop.advice; public enum Scope { PER_VM, PER_CLASS, PER_INSTANCE, PER_JOINPOINT }
And it's usage in JDK 1.5
package com.mypackage; @Aspect (scope=org.jboss.aop.advice.Scope.PER_VM) public class SomeAspect { }
The usage in JDK 1.4.2 is similar:
package com.mypackage; /** * @@org.jboss.aop.Aspect (scope=org.jboss.aop.advice.Scope.PER_VM) */ public class SomeAspect { //... }
However the declaration of the enumeration is different in 1.4.2:
package org.jboss.aop.advice; import java.io.ObjectStreamException; public class Scope extends org.jboss.lang.Enum { private Scope(String name, int v) { super(name, v); } public static final Scope PER_VM = new Scope("PER_VM", 0); public static final Scope PER_CLASS = new Scope("PER_CLASS", 1); public static final Scope PER_INSTANCE = new Scope("PER_INSTANCE", 2); public static final Scope PER_JOINPOINT = new Scope("PER_JOINPOINT", 3); private static final Scope[] values = {PER_VM, PER_CLASS, PER_INSTANCE, PER_JOINPOINT}; Object readResolve() throws ObjectStreamException { return values[ordinal]; } }
To create your own enum class for use within annotations, you need to inherit from org.jboss.lang.Enum. Each enum has two values, a String name, and an integer ordinal. The value used for the ordinal must be the same as it's index in the static array.
The annotation compiler allows you to use annotations within annotations. This is best illustrated with an example. The definitions of the annotation interfaces in JDK 1.4.2:
com.mypackage; public interface Outer { Inner[] values(); }
com.mypackage; public interface Inner { String str(); int integer(); }
The annotations can be applied as follows
com.mypackage; /** * @@com.mypackage.Outer ({@@com.mypackage.Inner (str="x", integer=1), \ @@com.mypackage.Inner (str="y", integer=2)}) */ public class Test { Inner[] values(); }
In order to use the JDK 1.4.2 annotations you have to precompile your files with an annotation compiler.
To use the annotation compiler you can create a simple ant build.xml file
<?xml version="1.0" encoding="UTF-8"?> <project default="run" name="JBoss/AOP"> <target name="prepare">
Include the jars AOP depends on
<path id="javassist.classpath"> <pathelement path="../../../javassist.jar"/> </path> <path id="trove.classpath"> <pathelement path="../../../trove.jar"/> </path> <path id="concurrent.classpath"> <pathelement path="../../../concurrent.jar"/> </path> <path id="jboss.common.classpath"> <pathelement path="../../../jboss-common.jar"/> </path> <path id="jboss.aop.classpath"> <pathelement path="../../../jboss-aop.jar"/> </path> <path id="qdox.classpath"> <pathelement path="../../../qdox.jar"/> </path> <path id="classpath"> <path refid="javassist.classpath"/> <path refid="trove.classpath"/> <path refid="jboss.aop.classpath"/> <path refid="jboss.common.classpath"/> <path refid="concurrent.classpath"/> <path refid="qdox.classpath"/> </path>
Define the ant task that does the annnotation compilation
<taskdef name="annotationc" classname="org.jboss.aop.ant.AnnotationC" classpathref="jboss.aop.classpath" /> </target> <target name="compile" depends="prepare">
Compile the source files
<javac srcdir="." destdir="." debug="on" deprecation="on" optimize="off" includes="**"> <classpath refid="classpath"/> </javac>
Run the annotation compiler
<annotationc compilerclasspathref="classpath" classpath="." bytecode="true"> <src path="."/> </annotationc> </target> </project>
The org.jboss.aop.ant.AnnotationC ant task takes several parameters.
You cannot currently specify both bytecode and xml.
You can also run org.jboss.aop.ant.AnnotationC from the command line, you need
$ java -cp <all the JBoss AOP jars and the directory containing files we want to AOP> \ org.jboss.aop.annotation.compiler.AnnotationCompiler \ [-xml [-o outputfile ]] [-bytecode]<files>+
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 is:
$ annotationc <classpath> [-verbose] [-xml [-o outputfile]] [-bytecode] <dir_or_file>+
The other parameters are the same as above.