[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: Re: [aspectj-dev] interfaces, pointcuts, and libraries
|
Hi all,
Hi Ron,
Hi Wes,
Ron is exactly right. The original proposal was about using abstract
aspects outside. However I find the proposal from Jim was very
fascinating.
(That you can modify with || && exisiting pointcuts). Based on my
experience there is a great need for extensible pointcuts. Unfortunatly
there are currently only abstract pointcuts in the language, so most
people "abuse" abstract pointcuts and abstract aspects to emulate and
implement extensible pointcuts.
I created a typical sample, where I want to have extensible pointcuts.
public class C {
public static void main(String[] args) {
new C().m1();
System.out.println();
new SomeOherClass().m2();
System.out.println();
new C2().m3();
}
public void m1(){
try{
throw new Exception("M1 Should not be adviced");
}catch(Exception ex){
}
}
static aspect DoNotAdviceExceptionsInM2 extends
AdviceEmptyExceptionBodies{
pointcut ExcludeException():within(C);
}
}
class C2{
public void m3(){
try{
throw new Exception("m3 Should be only adviced once");
}catch(Exception ex){
}
}
}
class SomeOherClass{
public void m2(){
try{
throw new Exception("M2 Should not be adviced");
}catch(Exception ex){
}
}
static aspect DoNotAdviceExceptionsInM2 extends
AdviceEmptyExceptionBodies{
pointcut ExcludeException():within(SomeOherClass);
}
}
abstract aspect AdviceEmptyExceptionBodies{
pointcut ExceptionBodies():handler(Exception);
abstract pointcut ExcludeException();
before():ExceptionBodies()&&!ExcludeException(){
System.out.println(thisJoinPoint);
System.out.println("I "+this+" adviced wrongly "+thisJoinPoint);
System.out.println(((Exception)
thisJoinPoint.getArgs()[0]).getMessage());
}
}
Creates following output:
handler(catch(Exception))
I
de.aspectsoft.extensiblepointcuts.SomeOherClass$DoNotAdviceExceptionsInM2@6eb38a
adviced wrongly handler(catch(Exception))
M1 Should not be adviced
handler(catch(Exception))
I de.aspectsoft.extensiblepointcuts.C$DoNotAdviceExceptionsInM2@eed786
adviced wrongly handler(catch(Exception))
M2 Should not be adviced
handler(catch(Exception))
I de.aspectsoft.extensiblepointcuts.C$DoNotAdviceExceptionsInM2@eed786
adviced wrongly handler(catch(Exception))
m3 Should be only adviced once
handler(catch(Exception))
I
de.aspectsoft.extensiblepointcuts.SomeOherClass$DoNotAdviceExceptionsInM2@6eb38a
adviced wrongly handler(catch(Exception))
m3 Should be only adviced once
The code works as designed (AND I WANT THIS BEHAVIOUR), but I currently
do not see any (EASY) way to implement the desired behaviour of the
codefragment.
regards
Arno
P.S. I am on an businesstrip, so I have only access to a webmail mail
client, so please accept any misformatings caused by the webmail client.
Ron Bodkin <rbodkin@xxxxxxxxxxx> schrieb am 28.07.2003, 21:27:29:
> 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
> > To: "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
> >
> _______________________________________________
> aspectj-dev mailing list
> aspectj-dev@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-dev