The principles behind declare error/warning, and the example used here is exactly the same as in the XML example. But the errors/warnings are declared differently using annotations.
import org.jboss.aop.DeclareWarning; @Aspect public class DeclareAspect { @DeclareWarning (expr="class($instanceof{VehicleDAO}) AND !has(public void *->save())", msg="All VehicleDAO subclasses must override the save() method.") public static Pointcut warning1; @DeclareWarning (expr="call(Driver->new(..)) AND within(*DAO)", msg="DAO classes should not access the Driver class") public static Pointcut warning2; @DeclareWarning (expr="call(* Driver->*(..)) AND withincode(* *DAO->save())", msg="DAO classes should not access the Driver class") public static Pointcut warning3; }
import org.jboss.aop.DeclareError; import org.jboss.aop.Aspect; import org.jboss.aop.pointcut.Pointcut; @Aspect public class DeclareAspect { @DeclareError (expr="class($instanceof{VehicleDAO}) AND !has(public void *->save())", msg="All VehicleDAO subclasses must override the save() method.") public static Pointcut warning1; @DeclareError (expr="call(Driver->new(..)) AND within(*DAO)", msg="DAO classes should not access the Driver class") public static Pointcut warning2; @DeclareError (expr="call(* Driver->*(..)) AND withincode(* *DAO->save())", msg="DAO classes should not access the Driver class") public static Pointcut warning3; }
Now if you run the example:
To compile and run with JDK 5:
$ ant run.aopc.50
It will generate the following output
_aopc50.annotated: [aopc] WARNING: declare-warning condition [aopc] 'call(Driver->new(..)) AND within(*DAO)' [aopc] was broken for constructor call: CarDAO.save()V calls Driver.new()V [aopc] DAO classes should not access the Driver class [aopc] WARNING: declare-warning condition [aopc] 'call(* Driver->*(..)) AND withincode(* *DAO->save())' [aopc] was broken for method call:CarDAO.save()V calls Driver.method()V [aopc] DAO classes should not access the Driver class [aopc] WARNING: declare-warning condition [aopc] 'class($instanceof{VehicleDAO}) AND !has(public void *->save())' [aopc] was broken for class MotorbikeDAO [aopc] All VehicleDAO subclasses must override the save() method. [aopc] Build Successful: 438 ms _run.aopc.50.annotated: [java] ---- Start ---- [java] Car DAO save
Note that when using compile time instrumentation the warnings are generated during the aopc phase.
(To run with JDK 1.4 use $ ant run.aopc.14 as shown in the annotated examples guide.)
Run the example with JDK 5:
$ ant run.loadtime.50
It will generate the following output
_run.loadtime.50.annotated: [java] ---- Start ---- [java] WARNING: declare-warning condition [java] 'call(Driver->new(..)) AND within(*DAO)' [java] was broken for constructor call: CarDAO.save()V calls Driver.new()V [java] DAO classes should not access the Driver class [java] WARNING: declare-warning condition [java] 'call(* Driver->*(..)) AND withincode(* *DAO->save())' [java] was broken for method call:CarDAO.save()V calls Driver.method()V [java] DAO classes should not access the Driver class [java] Car DAO save [java] WARNING: declare-warning condition [java] 'class($instanceof{VehicleDAO}) AND !has(public void *->save())' [java] was broken for class MotorbikeDAO [java] All VehicleDAO subclasses must override the save() method.Note that now the warnings are displayed when running the application, as the classes are transformed when loaded. (To run with JDK 1.4 use $ ant run.aopc.14 as shown in the annotated examples guide.)
import org.jboss.aop.DeclareError; @Aspect public class DeclareAspect { @DeclareError (expr="class($instanceof{VehicleDAO}) AND !has(public void *->save())", msg="All VehicleDAO subclasses must override the save() method.") Pointcut warning1; @DeclareError (expr="call(Driver->new(..)) AND within(*DAO)", msg="DAO classes should not access the Driver class") Pointcut warning2; @DeclareError (expr="call(* Driver->*(..)) AND withincode(* *DAO->save())", msg="DAO classes should not access the Driver class") Pointcut warning3; }
$ ant run.aopc.50 Buildfile: build.xml ... _aopc50.annotated: [aopc] ERROR: declare-error condition [aopc] 'call(Driver->new(..)) AND within(*DAO)' [aopc] was broken for constructor call: CarDAO.save()V calls Driver.new()V [aopc] DAO classes should not access the Driver class [aopc] java.lang.RuntimeException: ERROR: declare-error condition [aopc] 'call(Driver->new(..)) AND within(*DAO)' [aopc] was broken for constructor call: CarDAO.save()V calls Driver.new()V [aopc] DAO classes should not access the Driver class [aopc] at org.jboss.aop.instrument.DeclareChecker.checkDeclares(DeclareChecker.java:124) [aopc] at org.jboss.aop.instrument.DeclareChecker.checkDeclares(DeclareChecker.java:57) [aopc] at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.edit(CallerTransformer.java:472) [aopc] at javassist.expr.ExprEditor.doit(ExprEditor.java:136) [aopc] at javassist.CtBehavior.instrument(CtBehavior.java:362) [aopc] at org.jboss.aop.instrument.CallerTransformer.applyCallerPointcuts(CallerTransformer.java:69) [aopc] at org.jboss.aop.instrument.Instrumentor.applyCallerPointcuts(Instrumentor.java:495) [aopc] at org.jboss.aop.instrument.Instrumentor.transform(Instrumentor.java:562) [aopc] at org.jboss.aop.AspectManager.translate(AspectManager.java:564) [aopc] at org.jboss.aop.AspectManager.transform(AspectManager.java:482) [aopc] at org.jboss.aop.standalone.Compiler.compileFile(Compiler.java:251) [aopc] at org.jboss.aop.standalone.Compiler.compile(Compiler.java:184) [aopc] at org.jboss.aop.standalone.Compiler.main(Compiler.java:67) [aopc] [error] failed to transform: CarDAO.. Do verbose mode if you want full stack trace. [aopc] Exception in thread "main" java.lang.RuntimeException: failed to transform: CarDAO [aopc] at org.jboss.aop.instrument.Instrumentor.transform(Instrumentor.java:615) [aopc] at org.jboss.aop.AspectManager.translate(AspectManager.java:564) [aopc] at org.jboss.aop.AspectManager.transform(AspectManager.java:482) [aopc] at org.jboss.aop.standalone.Compiler.compileFile(Compiler.java:251) [aopc] at org.jboss.aop.standalone.Compiler.compile(Compiler.java:184) [aopc] at org.jboss.aop.standalone.Compiler.main(Compiler.java:67) [aopc] Caused by: javassist.CannotCompileException: by java.lang.RuntimeException: ERROR: declare-error condition [aopc] 'call(Driver->new(..)) AND within(*DAO)' [aopc] was broken for constructor call: CarDAO.save()V calls Driver.new()V [aopc] DAO classes should not access the Driver class [aopc] at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.edit(CallerTransformer.java:501) [aopc] at javassist.expr.ExprEditor.doit(ExprEditor.java:136) [aopc] at javassist.CtBehavior.instrument(CtBehavior.java:362) [aopc] at org.jboss.aop.instrument.CallerTransformer.applyCallerPointcuts(CallerTransformer.java:69) [aopc] at org.jboss.aop.instrument.Instrumentor.applyCallerPointcuts(Instrumentor.java:495) [aopc] at org.jboss.aop.instrument.Instrumentor.transform(Instrumentor.java:562) [aopc] ... 5 more
See how the compiler stops at the first error and execution stops. (To run with JDK 1.4 use $ ant run.aopc.14 as shown in the annotated examples guide.)
$ ant run.loadtime.50 ... _run.loadtime.50.annotated: [java] ---- Start ---- [java] ERROR: declare-error condition [java] 'call(Driver->new(..)) AND within(*DAO)' [java] was broken for constructor call: CarDAO.save()V calls Driver.new()V [java] DAO classes should not access the Driver class [java] java.lang.RuntimeException: ERROR: declare-error condition [java] 'call(Driver->new(..)) AND within(*DAO)' [java] was broken for constructor call: CarDAO.save()V calls Driver.new()V [java] DAO classes should not access the Driver class [java] at org.jboss.aop.instrument.DeclareChecker.checkDeclares(DeclareChecker.java:124) [java] at org.jboss.aop.instrument.DeclareChecker.checkDeclares(DeclareChecker.java:57) [java] at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.edit(CallerTransformer.java:472) [java] at javassist.expr.ExprEditor.doit(ExprEditor.java:136) [java] at javassist.CtBehavior.instrument(CtBehavior.java:362) [java] at org.jboss.aop.instrument.CallerTransformer.applyCallerPointcuts(CallerTransformer.java:69) [java] at org.jboss.aop.instrument.Instrumentor.applyCallerPointcuts(Instrumentor.java:495) [java] at org.jboss.aop.instrument.Instrumentor.transform(Instrumentor.java:562) [java] at org.jboss.aop.AspectManager.translate(AspectManager.java:564) [java] at org.jboss.aop.AspectManager.transform(AspectManager.java:482) [java] at org.jboss.aop.standalone.AOPTransformer.transform(AOPTransformer.java:28) [java] at sun.instrument.TransformerManager.transform(TransformerManager.java:122) [java] at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:155) [java] at java.lang.ClassLoader.defineClass1(Native Method) [java] at java.lang.ClassLoader.defineClass(ClassLoader.java:620) [java] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) [java] at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) [java] at java.net.URLClassLoader.access$100(URLClassLoader.java:56) [java] at java.net.URLClassLoader$1.run(URLClassLoader.java:195) [java] at java.security.AccessController.doPrivileged(Native Method) [java] at java.net.URLClassLoader.findClass(URLClassLoader.java:188) [java] at java.lang.ClassLoader.loadClass(ClassLoader.java:306) [java] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) [java] at java.lang.ClassLoader.loadClass(ClassLoader.java:251) [java] at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) [java] at Driver.createVehicles(Driver.java:24) [java] at Driver.main(Driver.java:19) [java] [error] failed to transform: CarDAO.. Do verbose mode if you want full stack trace. [java] Car DAO save [java] [error] failed to transform: MotorbikeDAO.. Do verbose mode if you want full stack trace.Again you can see how the first broken condition causes execution to stop. (To run with JDK 1.4 use $ ant run.aopc.14 as shown in the annotated examples guide.)