Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] How to exclude nested matching method executions?

Hi,

On 9 December 2011 14:15, Mark <mark.kharitonov@xxxxxxxxx> wrote:
> Here is a concrete extender - ResourceHandlerLoggerAspect:
> ============================================================
> public aspect ResourceHandlerLoggerAspect extends LoggerAspect {
>  declare @type : @Path * : @LogMe;
>  declare parents: (@Path *) implements ILoggable;
>
>  pointcut loggedScope() : within(@Path *);
>  pointcut loggedMethods() : execution(@(GET || PUT || POST || DELETE)
> public * *.*(..));
> }
> ============================================================
>
> I have a feeling that it should be easier now to deal with the repeating
> exception logging, though it still escapes my understanding how to do it.

Simplest way would be to keep a list of exceptions you've printed:

 List<Integer> loggedExceptions = new ArrayList<>();

after() throwing (Exception e): loggedScope() && loggedMethods() {
  if (!loggedExceptions.contains(System.identityHashcode(e)) {
   logAfterThrowing(getLogger(thisJoinPointStaticPart), thisJoinPoint, e);
   loggedExceptions.add(System.identityHashcode(e));
  }
 }

possibly with some advice on the top level interesting method to empty
the list when the control flow finishes:

  after() loggedMethods() && !cflowbelow(loggedMethods()) {
    loggedExceptions.clear();
  }

it is a bit crude but I think it'd work.

cflow could be used by itself and may only log the exception once but
it would log it at the top most exit point rather than when it first
occurs.

after() throwing (Exception e): loggedScope() && loggedMethods() &&
!cflowbelow(loggedMethods()) {
}

this will stop you seeing exception that are thrown/caught and dealt
with before coming out of the top of the control flow - I don't think
that is ideal.

> In general, is it possible either from the pointcut definition or from the advice itself to deduce whether the same advice would be applied lower in the call stack?

the only tool you have is cflow()/cflowbelow() - these can be tricky
to get your brain around but are quite powerful.  A simple example is:

void a() {}
void b() {}

a() {
  b()
}

when you run a(), it calls b(), at that moment b() is in the 'control
flow' of a().  This control flow information can be used in your
pointcuts:

execution(* b()) - match when b() runs regardless of how we got there
execution(* b()) && cflow(execution(* a()) - match when b() runs and
it is running because of an earlier call to a()
execution(* b()) && !cflow(execution(* a()) - match when b() runs
except when it runs because of an earlier call to a()

Andy


Back to the top