Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] Excluding Particular Joinpoints

> Wes - you have waaay to much time on your hands man!  ;-)

No time at all - this was pocketed from a pattern in
  
  http://www.ibm.com/developerworks/java/library/j-aopwork7

(No one's publishing articles on logging with AspectJ,
even though there are plenty of ways to make a mess of it.)

Wes

> ------------Original Message------------
> From: "Conway. Fintan (IT Solutions)" <Fintan.Conway@xxxxxx>
> To: "Wes Isberg" <wes@xxxxxxxxxxxxxx>, aspectj-users@xxxxxxxxxxx
> Date: Thu, Dec-1-2005 2:37 AM
> Subject: RE: [aspectj-users] Excluding Particular Joinpoints
>
> Wes - you have waaay to much time on your hands man!  ;-)
> 
> -----Original Message-----
> From: aspectj-users-bounces@xxxxxxxxxxx
> [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Wes Isberg
> Sent: 01 December 2005 09:44
> To: aspectj-users@xxxxxxxxxxx
> Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> 
> 
> Hi all -
> 
> (To combine Ron and Bo Yi's answers...)
> 
> This is a vote for a client-visible API rather than annotations where
> the subject is not an annotation target (method or class).
> 
> Getting annotations off the enclosing-static-part only works if the 
> handler is in the annotated method, not in a called method.  Instead of
> saying, "Don't log this exception," this approach says, "Don't advise
> handlers in this method" (optionally conditioned on an exception 
> class).
> 
> But the developer might also want to say, "This code throws exceptions
> {of class E} that don't need to be logged" (regardless of where the
> handler is).  Or they might want to say, "When you log exceptions
> thrown, include [this interesting bit of context]."  To say it, they
> shouldn't have to refactor methods, e.g., to make the annotation 
> work for some handlers but not others.  Once the client is not only not
> oblivious but also participating, then think carefully about how to
> communicate with the aspect.
> 
> One way is directly:
> 
>   Logging.aspectOf().ignore(MyError.class);
> 
> That has the benefit of clarity, but commits to the aspect 
> implementation.  You can hide behind a static method:
> 
>   public static void ignore(Class exceptionClass) {
>      LoggingImpl.aspectOf().ignore(c);
>   }
> 
> For code that not only hides but also compiles without aspectJ, use
> stubs
> 
>   public static void ignore(Class exceptionClass) {
>      // advise me
>   }
> 
> implemented with ITD's (if non-static in subtypes) or advice:
> 
>   before(Class c) : execution(void Logging.ignore(Class)) && args(c) {
>      LoggingImpl.aspectOf().ignore(c);
>      // or...
>      ignore(c);
>   }
> 
> A ThreadLocal is another way to maintain this kind of mode-status that
> works whether the subject code in question runs later in time, in the
> context of something, or specific snippets of code. The hard part in
> Java is clearing the thread-local context which means boilerplate like
> 
>    myLocal.get().ignore(MyError.class);
>    try {
>       ... do stuff
>    } finally {
>      myLocal.get().dontIgnore(MyError.class);
>    }
> 
> That's easy in AspectJ; just have the threadlocal class keep the 
> context in a stack, and clear the stack to the same level on exiting a
> join point as it was on entering the join point:
> 
>    Object around() : stackPoints() {
>       int stackIndex = LogContext.stackIndex();
>       try {
>          return proceed();
>       } finally {
>          LogContext.setStackIndex(stackIndex);
>       }
>    }
> 
> Then any logging system, AspectJ or otherwise, can inspect the context
> stack for instructions, additional context information to log, etc.
> 
> Using AspectJ to terminate means "this code" ends with the next
> enclosing 
> join point picked out by stackPoints().  That has its own problems.  
> When some code deep in the bowels that was invoked by "... do stuff" 
> expects MyError to be logged and it isn't, it might not
> be easy to find where it was suppressed (absent a facility to log when
> exception logging is suppressed :)  Then you go down the path of
> unsuppressing it, which might not be valid for other callers...
> 
> For a handler-specific call, you can terminate directly, just as you
> would in Java:
> 
>    myLocal.get().ignore(MyError.class);
>    ... do stuff
>    myLocal.get().dontIgnore(MyError.class);
> 
> So the client is managing the context directly (and needs 
> cleaner API's).
> 
> The power of stashing additional context in case you end up logging 
> something later is that it avoids pessimistic logging - logging in case
> something happens later and you want to know more about 
> what happened before that happened.  Instead of always 
> logging it, it logs only when something actually happens, as relevant
> context (and in the same message?).
> 
> So for this logging-context pattern, you typically
> 
> - define API's for publishing clients,
> 
> class LogContext {
>   void suppress(Class exceptionClass) { ... }
>   void dontSuppress(Class exceptionClass) { ... }
>   void addLogSupplement(String info) { ... }
>   ...
> }
> 
> - for subscribing clients,
> 
>     Class[] suppressedExceptions() { ... }
>     String[] getLogSupplements() { ... }
> 
> - and for managing clients, 
> 
>     int position() { ... }
>     void setPosition(int p) { ... }
> 
> - and then implement using threadlocals if not static convenience
> methods class LogContext {
>   static ThreadLocal<LogContext> sfLocal;
>   public static LogContext current()  { return sfLocal.get(); }
>   public static void suppress(Class exceptionClass) {
>     current().suppress(exceptionClass);
>   }
>   ...
> }
> .. and AspectJ to pop the context stack...
> 
> This solution adapts to most any blend of AspectJ/Java logging, from 
> no-AspectJ (with the context-clearing boilerplate above) to everything-
> done-in-aspects (e.g., automatically adding public method String
> parameters to the context when in verbose mode ...).  It makes other
> coders and managers happy if they can decide how much of the 
> implementation is in AspectJ, which is good for logging as an entry 
> app.
> 
> Most applications of AspectJ for logging/tracing get hung up on this 
> divide of aspect/client, particularly when trying to tailor output. In
> most real systems, the aspect does some top-down tracing, and the 
> client does some bottom-up logging.
> 
> Separating the two can make it hard to correlate the information and 
> you
> lose the opportunity for the aspects to make things easier for the
> client.  By contrast, if you make a common facility (i.e., if your
> clients are not all oblivious), your aspects can support some simple 
> but
> powerful API's for clients.  Beyond suppressing exception logging and
> supplementing logs, you can
> 
> o get context known to advice, e.g., source location
>    String getSourceLocation() {
>       ... stub, implemented by advice on caller
>    }
> 
> o tailor verbosity to particular contexts or modes
> 
> o serialize logging operations out to separate threads,
>   or defer logging until after client-specified critical sections
>   have completed
> 
> and so on...
> 
> So my rule would be if you're using annotations as a way for the 
> client to guide the work of an aspect, consider using an API instead
> unless what's being said is strongly related to the form of the
> annotation target (class or method) or to the content of the annotation
> - e.g., a verbosity flag:
> 
>    @Verbosity(INFO)
>    String doSomething() {..}
> 
> Wes
> 
> > ------------Original Message------------
> > From: "Ron Bodkin" <rbodkin@xxxxxxxxxxxxxx>
> > To: aspectj-users@xxxxxxxxxxx
> > Date: Wed, Nov-30-2005 10:19 PM
> > Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> >
> > Just to clarify my original posting, I was showing how to match
> > exception
> > handler join points that are enclosed inside annotated methods (or 
> > other
> > sources). The only way to do that is with code like I posted (you
> could 
> > put
> > it in an if pointcut designator if you like).
> > 
> > Dean's code is the right way to match join points (such as method
> > execution)
> > that exit by an exception from an annotated method.
> > 
> > -----Original Message-----
> > From: aspectj-users-bounces@xxxxxxxxxxx 
> > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Dean Wampler
> > Sent: Wednesday, November 30, 2005 9:57 PM
> > To: aspectj-users@xxxxxxxxxxx
> > Subject: Re: [aspectj-users] Excluding Particular Joinpoints
> > 
> > You can exclude the method annotation in the PCD itself. Here is a 
> > complete example:
> > 
> > TestExcludeExceptions.aj: Aspect that declares a nested method 
> > annotation "DontLog". Note the PCD that excludes methods with this 
> > annotation.
> > 
> > import java.lang.annotation.ElementType;
> > import java.lang.annotation.Target;
> > 
> > public aspect ExcludeExceptions {
> > 	@Target(ElementType.METHOD)
> > 	public static @interface DontLog {}
> > 	
> > 	pointcut watch(): execution (!@DontLog * *.*(..));
> > 	
> > 	after() throwing(Throwable th): watch() {
> > 		System.err.println("Oops! "+thisJoinPointStaticPart+":
> "+th);
> > 	}
> > }
> > 
> > TestExcludeExceptions.aj: Test routine. You'll see the advice "Oops!" 
> 
> > message only after calls to "failUnexpected()", because 
> > "failExpected()" has the marker annotation "DontLog". (The "okay()" 
> > method is for "background subtraction" - that's a bone for you other 
> > physicists out there... ;)
> > 
> > public class TestExcludeExceptions {
> > 	public void okay() {
> > 		System.out.println ("TestExcludeExceptions.okay():");
> > 	}
> > 	
> > 	@ExcludeExceptions.DontLog
> > 	public void failExpected() {
> > 		System.out.println
> ("TestExcludeExceptions.failExpected():");
> > 		throw new RuntimeException();
> > 	}
> > 	
> > 	public void failUnexpected() {
> > 		System.out.println
> ("TestExcludeExceptions.failUnexpected():");
> > 		throw new RuntimeException();
> > 	}
> > 	
> > 	public static void main(String[] args) {
> > 		TestExcludeExceptions tee = new TestExcludeExceptions();
> > 		tee.okay();
> > 		try {
> > 			tee.failExpected();
> > 		} catch (Throwable th) {}
> > 		try {
> > 			tee.failUnexpected();
> > 		} catch (Throwable th) {}
> >        }
> > }
> > 
> > dean
> > 
> > On 11/30/05, Ron Bodkin <rbodkin@xxxxxxxxxxxxxx> wrote:
> > >
> > >
> > >
> > > You can use the signature at the enclosing join point static part 
> to
> > get
> > the
> > > right Java reflective object (a Method or Constructor). For 
> example,
> > >
> > 
> ((MethodSignature)thisEnclosingJoinPointStaticPart.getSignature()).get
> > Method
> > ().getAnnotation(myAnnotationType);
> > >
> > >
> > >
> > > You probably want to have at least 2 cases for method and
> > constructor. To
> > be
> > > totally complete there are 6 cases (for advice, initialization, 
> > > pre-initialization and static initialization). To support static 
> > > initialization you'd want to have annotations on the class too.
> > >
> > >
> > >
> > > http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg00655.html
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Tobias 
> > > Dunn-Krahn
> > >  Sent: Wednesday, November 30, 2005 4:13 PM
> > >
> > >  To: aspectj-users@xxxxxxxxxxx
> > >  Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> > >
> > >
> > >
> > >
> > > Hi Ron,
> > >
> > >
> > >
> > > I agree that annotating the method is the cleanest proposal so far.
> > One
> > > problem though. I can't figure out how to examine annotations from 
> > > thisEnclosingJoinpointStaticPart (or the JoinPoint interface in 
> > > general).  Any hints?
> > >
> > >
> > >
> > > Tobias
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Ron Bodkin
> > >  Sent: Wednesday, November 30, 2005 2:32 PM
> > >  To: aspectj-users@xxxxxxxxxxx
> > >  Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> > >
> > >
> > >
> > > Hi Tobias,
> > >
> > >
> > >
> > > You can use annotations at the method level to address this: you
> > could
> > then
> > > look at thisEnclosingJoinPointStaticPart to see if there is an 
> > > appropriate annotation. If you find that the same exception is
> > handled
> > > differently in the same method, I'd suggest extracting a method to
> > deal
> > with
> > > this. This would be a lot cleaner than using a naming convention on
> > the
> > > methods.
> > >
> > >
> > >
> > > As you noted, it isn't possible to use variable annotations both
> > because
> > > they are not retained in the binary representation and AspectJ 
> > > relies
> > on
> > > binary representations for weaving. Also AspectJ doesn't in general
> > expose
> > > information about local variables (e.g., there is way to match
> > pointcuts
> > or
> > > expose join point information based on local variables). By the 
> same
> > token,
> > > you can't determine the name of the local variable being used in 
> the
> > catch
> > > block, so a naming convention like this wouldn't help with AspectJ.
> > This
> > is
> > > a good thing IMHO: it would be too brittle if renaming local
> > variables
> > would
> > > change pointcut matching.
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Tobias 
> > > Dunn-Krahn
> > >  Sent: Wednesday, November 30, 2005 2:03 PM
> > >  To: gregor@xxxxxxxxx; aspectj-users@xxxxxxxxxxx
> > >  Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> > >
> > >
> > >
> > > Gregor and Ron,
> > >
> > >
> > >
> > > Thanks for your suggestions.  Unfortunately in my case, I can't
> > determine
> > > from just the Throwable whether or not it should be logged.  For
> > example,
> > a
> > > FooBarException should be logged in some cases but not others,
> > depending
> > on
> > > the surrounding application logic.  Really the only way to 
> determine
> > this
> > is
> > > a decision on the part of developer, which is why I was 
> > > experimenting
> > with
> > > annotations.
> > >
> > >
> > >
> > > Perhaps I could use thisJoinPoint in combination with a naming
> > convention
> > > for the throwable, i.e. any throwable named "expectedThrowable" 
> > > would
> > not
> > be
> > > logged.  It would be nice if I could do something more explicit 
> > > (like
> > an
> > > annotation) but perhaps it's not possible.  Please let me know if
> > I've
> > > misunderstood something about your suggestions.
> > >
> > >
> > >
> > > Thanks,
> > >
> > > Tobias
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Gregor 
> > > Kiczales
> > >  Sent: Wednesday, November 30, 2005 1:26 PM
> > >  To: aspectj-users@xxxxxxxxxxx
> > >  Subject: RE: [aspectj-users] Excluding Particular Joinpoints
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Tobias 
> > > Dunn-Krahn
> > >
> > >
> > >
> > > I am using AspectJ in a project to log all handled exceptions.  In
> > general
> > > this is what I want, but in a small number of cases such exceptions
> > are
> > > "expected" and I do not wish to log them.
> > >
> > >
> > >
> > > aspect FooBarExceptionLoggingStrategy {
> > >
> > >
> > >
> > >   before(Throwable t): handler(Throwable) && args(t) {
> > >
> > >     if( shouldLog(t) )
> > >
> > >        log(t);
> > >
> > >   }
> > >
> > >
> > >
> > >   private boolean shouldLog(Throwable t) {
> > >
> > >     <<test whatever needs testing here>>
> > >
> > >   }
> > >
> > >
> > >
> > >   private void log(Throwable t) {
> > >
> > >     ...
> > >
> > >   }
> > >
> > > }
> > >
> > >
> > >
> > > The point being that you can test the exception in any way you want
> > before
> > > logging it.
> > >
> > > You could also pass thisJoinPoint or thisJoinPointStaticPart. If 
> you
> > want,
> > > you could
> > >
> > > move shouldLog into the actual pointcut, using if(shouldLog(t)).
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >  ________________________________
> > >
> > >
> > > From: aspectj-users-bounces@xxxxxxxxxxx 
> > > [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Tobias 
> > > Dunn-Krahn
> > >  Sent: Wednesday, November 30, 2005 11:42 AM
> > >  To: aspectj-users@xxxxxxxxxxx
> > >  Subject: [aspectj-users] Excluding Particular Joinpoints
> > >
> > > Hello All,
> > >
> > >
> > >
> > > I am using AspectJ in a project to log all handled exceptions.  In
> > general
> > > this is what I want, but in a small number of cases such exceptions
> > are
> > > "expected" and I do not wish to log them.  My pointcut definition 
> is
> 
> > > currently very simple; it matches all exception handlers except 
> > > those
> > that
> > > handle SocketTimeoutExceptions:
> > >
> > >
> > >
> > >   pointcut exceptionHandlers(Throwable t) : handler(Throwable+) &&
> > (args(t)
> > >
> > >       && !args(java.net.SocketTimeoutException));
> > >
> > >
> > >
> > > However, now I need to exclude matching of particular exception
> > handlers
> > > that are not distinguishable by type.  I tried creating a custom
> > annotation
> > > with target type LOCAL_VARIABLE and using this annotation to 
> > > decorate
> > the
> > > exception, but unfortunately annotations of this type are not
> > retained for
> > > runtime (and are therefore inaccessible).  Does anyone have any
> > suggestions?
> > >
> > >
> > >
> > > Thanks in advance,
> > >
> > > Tobias
> > >
> > >
> > > _______________________________________________
> > > aspectj-users mailing list
> > > aspectj-users@xxxxxxxxxxx 
> > > https://dev.eclipse.org/mailman/listinfo/aspectj-users
> > >
> > >
> > >
> > 
> > 
> > --
> > Dean Wampler
> > http://www.aspectprogramming.com
> > http://www.newaspects.com
> > http://www.contract4j.org
> > 
> > _______________________________________________
> > aspectj-users mailing list
> > aspectj-users@xxxxxxxxxxx 
> > https://dev.eclipse.org/mailman/listinfo/aspectj-users
> > 
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
> 
> 
> * ** *** ** * ** *** ** * ** *** ** * 
> This email and any files transmitted with it are confidential and 
> intended solely for the use of the individual or entity to whom they 
> are addressed. 
> Any views or opinions presented are solely those of the author, and do 
> not necessarily 
> represent those of ESB. 
> If you have received this email in error please notify the sender. 
>  
> Although ESB scans e-mail and attachments for viruses, it does not 
> guarantee 
> that either are virus-free and accepts no liability for any damage 
> sustained 
> as a result of viruses. 
>  
> * ** *** ** * ** *** ** * ** *** ** *
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
> 



Back to the top