## Annotated Declare Error/Warning

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.

### Declaring warnings

To declare a warning, you annotate a field with `@DeclareWarning`. This field must be within an `@Aspect` or `@InterceptorDef` annotated class. The type of the field does not actually matter, though Pointcut has been used in this example. `DeclareAspect` is not actually bound to anything and does no interceptions, its sole purpose in this example is as a vessel for the `@DeclareWarning` 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;
       }

- The first `@DeclareWarning` annotated field specifies that `VehicleDAO` and its subclasses must implement a void noargs save() method. This condition is broken in our example by the fact that `MotorbikeDAO` does not do so.
- The second `@DeclareWarning` annotated field specifies that none of the DAO classes can call the Driver constructor. This condition is broken in our example by the fact that `CarDAO.save()` tries to create a new `Driver` class.
- The third `@DeclareWarning` annotated field specifies that no method on any of the the DAO classes can call the Driver methods. This condition is broken in our example by the fact that `CarDAO.save()` tries to call a method on the `Driver` class

### Declaring errors

You declare an error in the same way as a warning, but you use the `@DeclareError` annotation instead. Modify `DeclareAspect` so that it becomes:

       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;
       }

#### Run the example compile-time instrumented

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.

#### Run the example load-time instrumented

      $ 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 SUCCESSFUL

Note that now the warnings are displayed when running the application, as the classes are transformed when loaded.

### Declaring errors

If we replace all the `@DeclareWarning` occurances with `@DeclareError` in `DeclareAspect`, an error will get thrown instead

    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;

    }

### declare-error precompiled

When running precompiled we get:

    $ 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.

### DeclareError loadtime

When running with loadtime transformations we get:

    $ 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.