JBoss.org Community Documentation

4.3.1. @Thrown annotated parameter

As shown in Table 4.1, “Annotated Parameters Table”, the presence of a @Thrown annotated parameter can be mandatory depending on the advice type and its parameters.

This annotation is available only for after-throwing and finally advices. For after-throwing advices this parameter is always mandatory:

public class Aspect
{
   public void throwing1(@Thrown RuntimeException thrownException)
   {
      ...
   }

   public void throwing2()
   {
      ...
   }
}


<aop>
   <aspect class="Aspect"/>
   <bind pointcut="...">
      <throwing aspect="Aspect" name="throwing1"/>
      <throwing aspect="Aspect" name="throwing2"/>
   </bind>
</aop>

The advice throwing1 follows this rule; advice throwing2, on the other hand, is invalid, because it does not contain the mandatory @Thrown annotated parameter.

For finally advices, the @Thrown annotation is compulsory only if a @Return annotated parameter is present. This way, a finally advice can identify whether the return value is valid or not. If the @Thrown parameter is null, it means that the joinpoint returned normally and that the value contained in the @Return annotated-parameter is valid. Otherwise, the value contained in @Return annotated parameter must be ignored (it will be null if the return type is not primitive, 0 if it is a primitive number or false if it is boolean). If the finally advice does not receive the joinpoint return value, the use of the @Thrown annotated parameter is optional and, as expected, its value will be null if the joinpoint being intercepted did not throw an exception. Take a look at the next example:

public class Aspect
{
   public void finally1(@Thrown Throwable thrownException)
   {
      ...
   }

   public void finally2()
   {
      ...
   }

   public void finally3(@Return int returnedValue, @Thrown Throwable thrownException)
   {
      if (thrownException == null)

      {

         //We returned normally, the @Return parameter is valid

         int i = returnedValue;

      }

      else

      {

         //An exception happened while invoking the target joinpoint

         //The return value is invalid

      }

    }

   public void finally4(@Return int returnedValue)
   {
      ...
   }

}


<aop>
   <aspect class="Aspect"/>
   <bind pointcut="execution(public int *->*(..))">
      <finally aspect="Aspect" name="finally1"/>
      <finally aspect="Aspect" name="finally2"/>

      <finally aspect="Aspect" name="finally3"/>

      <finally aspect="Aspect" name="finally4"/>

   </bind>
</aop>

This example binds four finally advices to the execution of all public methods that return an int value. Take note on the type of the @Thrown-annotated parameters, which must be Throwable for this type of advice.

The presence of @Thrown is not mandatory in advices finally1() and finally2(), because they do not have a @Return annotated parameter. Hence, both advices are valid. Besides, finally1() will receive a non-null exception only when the joinpoint being intercepted throws an exception.

For advice method finally3() the presence of a @Thrown annotated parameter is mandatory because this advice also has a @Return annotated parameter. If an exception happens when invoking the target joinpoint, this advice will receive a non-null @Thrown parameter, meaning that the @Return annotated parameter is invalid. If the joinpoint completes normally, the @Thrown annotated parameter will be null and the @Return annotated parameter will contain the return value of the target joinpoint.

The finally4() advice is invalid, it contains a @Return parameter, but has no @Thrown annotated parameter. Finally advices require a @Thrown parameter if a @Return annotated parameter is present.