Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Fixed scrollbar

...

Scrollbar

...

Service Advisors

Service advice represents a powerful meta-programming facility available to services. In fact, it is a kind of limited Aspect Oriented Programming.

...

You could track down the implementation of each service and fix the logic that provides a return value ... or you could advise the methods:

Code Block

  @Match("*")
  public static void adviseNonNull(MethodAdviceReceiver receiver)
  {
    MethodAdvice advice = new MethodAdvice()
    {
      void advise(Invocation invocation)
      {
        invocation.proceed();

        if (invocation.getResultType().equals(String.class) && invocation.getResult() == null)
          invocation.overrideResult("");
      }
    };

    receiver.adviseAllMethods(advice);
  };

...

Advice is pretty efficient, but it is still better to apply it only to methods that make sense. We can improve the service advisor method in our example to only advise methods that return String:

Code Block

  @Match("*")
  public static void adviseNonNull(MethodAdviceReceiver receiver)
  {
    MethodAdvice advice = new MethodAdvice()
    {
      void advise(Invocation invocation)
      {
        invocation.proceed();

        if (invocation.getResult().equals(null))
          invocation.overrideResult("");
      }
    };

    for (Method m : receiver.getServiceInterface().getMethods())
    {
      if (m.getReturnType().equals(String.class))
        receiver.adviseMethod(m, advice);
    }
  };

...

Logging advice is built into Tapestry. You can apply logging advice to your services very easily:

Code Block

  @Match("*")
  public static void adviseLogging(LoggingAdvisor loggingAdvisor, Logger logger, MethodAdviceReceiver receiver)
  {
    loggingAdvisor.addLoggingAdvice(logger, receiver);
  }

...

Annotation driven advisors

Since
since5.2
 
Starting from version 5.2, Tapestry supports annotation-driven advise methods. If the @Advise annotation is present, the advise method can be arbitrary named, as shown in the following example.

Code Block

  @Advise
  @Match("*DAO")
  public static void byServiceId(MethodAdviceReceiver receiver)
  {
    ...
  }

...

Alternatively, marker annotations can be placed on the advise method to match a specific service.

Code Block

  @Advise
  @Blue
  public static void byMarkerAnnotation(MethodAdviceReceiver receiver)
  {
    ...
  }

...

By default, @Advise annotation applies the advice to any service matched by the @Match or marker annotations. You can limit the matching to a single service interface, as shown in the following example.

Code Block

  @Advise(serviceInterface=MyService.class)
  @Match("*DAO")
  public static void byMatchAnnotation(MethodAdviceReceiver receiver)
  {
    ...
  }

In the example above, the advice is applied to any implementation of MyService interfaces whose id matches the "*DAO" pattern.

Code Block

  @Advise(serviceInterface=MyService.class)
  @Blue
  public static void byMarkerAnnotation(MethodAdviceReceiver receiver)
  {
    ...
  }

...

It is not recommended that you mix advice and decoration. If you do, decoration take precedence; all decorators will be in effect before any advice (internally, they are two separate steps, with advice being processed and the result of that used by the decorators).

...

 

Scrollbar