[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-dev] interfaces, pointcuts, and libraries

Hi Wes,

To clarify a bit, the original proposal _was_ to allow references to abstract pointcuts outside derived aspects. However, Jim made a good counterproposal of allowing extensible aspects rather than references to abstract pointcuts. As your note points out, references to abstract pointcuts would raise interesting questions. 

Extensible pointcuts shouldn't require instantiation of any aspects that extend them. They aren't abstract pointcuts at all, which would require this. Instead, there is a single global definition of a concrete pointcut that is held in the defining aspect.

Whenever another aspect extends it, the behavior is like for inter-type declarations: the pointcut in the original aspect is extended. You could use syntax like:

declare extension: AA.apc(): {pointcut};

so you'd have
aspect AA {
     extensible // required, or always allow inter-type extension?
     pointcut apc() : {base definition};
}

If AA were abstract, it would behave the same as if apc() were not extensible in concrete aspects derived from it.

Ron

Ron Bodkin
Chief Technology Officer
New Aspects of Security
m: (415) 509-2895

> ------------Original Message-------------
> From: Wes Isberg <wes@xxxxxxxxxxxxxx>
> To: "aspectj-dev@xxxxxxxxxxx" <aspectj-dev@xxxxxxxxxxx>
> Date: Mon, Jul-28-2003 12:10 PM
> Subject: Re: [aspectj-dev] interfaces, pointcuts, and libraries
> 
> Hi Arno -
> 
> You point out that we often want to recompose a pointcut.
> One way is to redefine a concrete pointcut:
> 
> ------ SuperPointcut.java
> 
> abstract aspect AA {
>      pointcut publicMethodCalls() : call(public * *(..))
>          && !within(AA+);
>      before() : publicMethodCalls() {
>          System.out.println("public method call: " +
>                               thisJoinPointStaticPart);
>      }
> }
> 
> //aspect A extends AA {}
> aspect B extends AA {
>      pointcut publicMethodCalls() : AA.publicMethodCalls()
>          && !call(void java..*.*(..));
> }
> 
> public class SuperPointcut {
>      public static void main(String[] a) {
>          new C().run();
>      }
> }
> class C {
>      public void run(){
>          System.out.println("run()"); // advise this?
>      }
> }
> 
> ------
> The aspect A would advise the call to System.out.println(String),
> while the aspect B does not.
> 
> Do you think that would help?  Your library aspects can have
> concrete pointcuts which are referred to and qualified by
> the subaspects for a particular configuration.
> 
> Wes
> 
> Arno Schmidmeier wrote:
> > Hi all,
> > Hello Wes,
> > 
> > the current abstract pointcut behaviour is fine with me, asl long as I use it 
> > as a real abstract pointcut.
> > 
> > However I often have to abuse abstract pointcuts to emulate something what I 
> > have named extensible pointcuts. (One of my requests for 1.1)
> > 
> > I have the impression, that this feature would be give Adrian, all what he 
> > needs to implement and would fit more clearly into the language. Please tell 
> > me if I am wrong.
> > 
> > Unfortunatly I can imagine, that this causes some headache with incremental 
> > compile, weave. ...
> > 
> > Some motivations examples:
> > 
> > 1. Exception logging.
> > I found very often a general rule, that all caught runtimeexception, which 
> > might have caused some harm, should be logged to stderr, ...
> > 
> > so following advice with pointcut would do it:
> > 
> > before(Exception ex):handler(Exception)&&args(ex){
> >    ex.printStackTrace(); // some other stuff...
> > }
> > 
> > It is pretty naturally to move this logic to a kind of library aspect. 
> > Unfortunatly, there are always some exceptions form the general rule in the 
> > code base. Places, where the advice should not be applied.
> > 
> > So I would like to say:
> > 
> > abstract aspect LogExceptions{
> > 
> > abstract pointcut mustNotLog();
> > before(Exception ex):handler(Exception)&&args(ex)&&!mustNotLog(){
> >    ex.printStackTrace(); // some other stuff...
> > }
> > 
> > So I can have one aspect per project, where I limit the scope for the library 
> > aspect. (with a concrete aspect).
> > In practical code, this causes a very ugly concrete aspect.
> > 
> > What I would prefere to have is something like:
> > 
> > abstract aspect LogExceptions{
> > 
> > extensible pointcut mustNotLog();
> > before(Exception ex):handler(Exception)&&args(ex)&&!mustNotLog(){
> >    ex.printStackTrace(); // some other stuff...
> > }
> > }
> > 
> > somewhere else:
> > declare pointcut LogException() extends: &&within(SomeClasss);
> > 
> > and somewhere else:
> > declare pointcut LogException() extends: &&within(SomeClasss);
> > 
> > This specific feature can be also used the other way round, motivated by my 
> > original post:
> > To add some joinpoint to an aspect. For this case I have found some idioms to 
> > work around, however I find them everything else than handy.
> > However for the case, where I want to exclude some joinpoints with extensible 
> > pointcuts I do not jet know a solution.
> > 
> > kind regards
> >    Arno
> > 
> > 
> >       
> > }
> > 
> > 
> > 
> > 
> > 
> > On Saturday 26 July 2003 23:09, Wes Isberg wrote:
> > 
> >>Another question is whether abstract aspects could play the same role.
> >>While extending aspects is less flexible, it has the property that
> >>the implementation is determinate for incremental weaving.
> >>
> >>Here's some pseudo-code for a programmer using a library of J2EE
> >>pointcuts that is implemented by different vendors.  The last step
> >>can be the selection of the vendor, when deploying:
> >>
> >>------- pseudo-code...
> >>---- AspectJ J2EE library
> >>
> >>abstract aspect EjbPointcuts {
> >>    abstract pointcut ejbInit();
> >>    abstract pointcut ejbActivation();
> >>    abstract pointcut ejbPassivation();
> >>    abstract pointcut ejbPersisting();
> >>    abstract pointcut ejbMessage();
> >>    ...
> >>}
> >>abstract aspect JmsPointcuts { ... }
> >>abstract aspect ServletPointcuts { ... }
> >>abstract aspect JSPPointcuts { ... }
> >>
> >>---- {vendor} J2EE library
> >>
> >>abstract aspect VendorEjbPointcuts extends EjbPointcuts {
> >>     {define pointcuts}...
> >>}
> >>...
> >>
> >>---- programmer writes to AspectJ J2EE library
> >>
> >>abstract aspect BankTransactions extends EjbPointcuts {
> >>     Object around() : ejbMessage()
> >>         && call(void Account.deposit(int)) {
> >>         ...
> >>     }
> >>     ...
> >>}
> >>
> >>---- application assembler/deployer hooks everything up
> >>
> >>aspect BankTransactionsAssembly extends BankTransactions {
> >>     declare parents: BankTransactions extends VendorEjbPointcuts;
> >>}
> >>
> >>------- end of pseudo-code...
> >>
> >>This approach poses single-inheritance problems that might drive
> >>towards a single abstract aspect and deter reuse of other
> >>abstract aspects, so it's obviously not ideal.  It might lead to
> >>a practice of using the library pointcuts from other aspects:
> >>
> >>----
> >>-- programmer code
> >>/** concretize the EjbPointcuts for use */
> >>abstract aspect BankTransactionPoints extends EjbPointcuts {
> >>     ...
> >>     public pointcut depositTransaction() : ejbMessage()
> >>          && call(void Account.deposit(int);
> >>}
> >>
> >>aspect BankTransactions extends Transactions {
> >>     /** concretize the abstract pointcuts in Transactions */
> >>     pointcut transactionalMessage() :
> >>         BankTransactionPoints.depositTransaction();
> >>     ...
> >>}
> >>-- application assembler/deployer
> >>
> >>aspect BankTransactionsAssembly extends BankTransactions {
> >>     declare parents: BankTransactionPoints extends VendorEjbPointcuts;
> >>}
> >>
> >>----
> >>
> >>This approach localizes the pointcut definitions in the vendor aspect,
> >>which is loaded before any aspect or class that is affected by
> >>the aspect, so it preserves incremental load-time weaving.
> >>(Indeed, a vendor controlling the weaver could implement custom
> >>join points not based on the normal Java programming model without
> >>affecting the AspectJ language.)
> >>
> >>So before I'd want to support interface pointcuts that prevented
> >>implementations of AspectJ from doing incremental weaving, I'd like
> >>to see a few libraries using abstract aspects and know that they
> >>can't do what people would like to do with libraries.
> >>
> >>Wes
> >>
> >>Adrian Colyer wrote:
> >>
> >>>AspectJ lets us declare pointcuts within aspects, classes and interfaces.
> >>>To create 'library' pointcuts I need to be able to declare pointcuts in
> >>>an interface (and let users of the library program to the interface), and
> >>>then have implementers of the interface provide concrete implementations
> >>>of those pointcuts. Exploring the behaviour of AspectJ 1.1 I see that we
> >>>are part of the way there, but not fully. What I am about to describe is
> >>>partially bug and partially feature request...
> >>>
> >>>Today I can write:
> >>>
> >>>public interface Foo {
> >>>
> >>>   public pointcut bar();
> >>>
> >>>}
> >>>
> >>>This compiles happily, and I can refer to Foo.bar() in advice (it doesn't
> >>>match any joinpoints).
> >>>
> >>>If I write
> >>>
> >>>class C implements Foo {}
> >>>
> >>>this does not cause a compilation error (I believe it should, since C
> >>>does not define pointcut bar which it's interface contract says it
> >>>should).
> >>>
> >>>If I write
> >>>
> >>>class C implements Foo {
> >>>  public pointcut bar() : execution(... ...);
> >>>}
> >>>
> >>>this compiles happily. Writing advice against Foo.bar does not match
> >>>anything, writing advice against C.bar() matches the execution
> >>>joinpoints. The desired behaviour is that writing advice against Foo.bar
> >>>should match against the C definition.
> >>>
> >>>If I write
> >>>
> >>>aspect A implements Foo {}
> >>>
> >>>this does not cause a compilation error (I believe it should, since C
> >>>does not define pointcut bar()).
> >>>
> >>>
> >>>If I change the interface definition to
> >>>
> >>>public interface Foo {
> >>>  public abstract pointcut bar();
> >>>}
> >>>
> >>>then compilation of A fails with "inherited abstract pointcut Foo.bar()
> >>>is not made concrete in A" (good, but tells me that the pointcut is not
> >>>being implicitly made abstract when defined in an interface). Compilation
> >>>of the empty C declaration still does not produce the compilation error.
> >>>
> >>>How I think I would like this to behave is that pointcuts declared in
> >>>interfaces are implicitly abstract (just like method definitions in
> >>>interfaces). If a class or aspect declares that it implements the
> >>>interface without providing a concrete definition of the pointcut then
> >>>this is a compilation error.  Clients should be able to write advice
> >>>against the interface, and the advice will apply to joinpoints matching
> >>>any of the  concrete implementations of interface in the system (same
> >>>rules as for abstract / concrete aspect pairs).
> >>>
> >>>Why this is important:
> >>>* I  can create a standard interface that clients program to
> >>>* Multiple parties can implement the interface to provide concrete
> >>>implementations that make sense within their system. These can even be
> >>>binary so that implementation details are never exposed to clients.
> >>>
> >>>What do others think?
> >>>
> >>>-- Adrian
> >>>Adrian_Colyer@xxxxxxxxxx
> >>
> >>_______________________________________________
> >>aspectj-dev mailing list
> >>aspectj-dev@xxxxxxxxxxx
> >>http://dev.eclipse.org/mailman/listinfo/aspectj-dev
> > 
> > 
> 
> _______________________________________________
> aspectj-dev mailing list
> aspectj-dev@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-dev
>