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:
$ ant
It will generate the following output
Buildfile: build.xml prepare: compile: [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. run: [java] ---- Start ---- [java] Car DAO save BUILD SUCCESSFUL
Note that when using compile time instrumentation the warnings are generated during the aopc phase.
$ ant run.50.instrumented
run.50.instrumented: [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. BUILD SUCCESSFULNote that now the warnings are displayed when running the application, as the classes are transformed when loaded.
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 Buildfile: build.xml prepare: compile: [javac] Compiling 5 source files to C:\cygwin\home\Kab\cvs\jboss-head\aop\docs\examples\annotated-declare [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.
$ ant run.50.instrumented Buildfile: build.xml prepare: compile50standalone: [javac] Compiling 5 source files to C:\cygwin\home\Kab\cvs\jboss-head\aop\docs\examples\annotated-declare run.50.instrumented: [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.