Groovy and AOP

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Groovy and AOP

Gavin Grover

Hi Groovy developers

 

I've a question about how many AOP features does, and will, Groovy support. I realise the coming MOP will have some, have read about intercepting method calls and property accesses, and injecting into Expando, but can't find any more specifics.

 

About 18 months ago, I tried using AspectJ with classes compiled with Groovy beta 9 or 10. I've long lost the files, but remember a few points re why I gave it up.

 

Your design goal is that groovyc-made classes can be RUN by Java as if they were javac-made (except for GroovyObject as the base class), but groovyc-made classes weren't able to be WEAVED INTO by Java tools like AspectJ as if they were javac-made. Eg:

(1)The "withincode" pointcut worked, but returned many extra Groovy-internal method calls. It had to be supplemented by more specific pointcuts (eg, call, initialization, staticinit, preinit, exception) to be useful.

(2)The "execution" pointcut didn't work because the method calls from groovyc-made code redirected the call thru "invokeMethod" in code not controlled by AspectJ.

(3)"!public && !protected && !private" in an AspectJ pointcut doesn't select methods specified with default access in Groovy because of the different semantics.

(4)You couldn't weave into Closures, not knowing the names of them beforehand (eg, MyClass_closure3_closure7).

(5)The "this", "args", and "target" contexts were exposed correctly, introductions worked too, but I didn't try out any more advanced AspectJ features.

 

I also remember file size bloat. If a javac-made class file was 3k, when AspectJ-woven it would be 4 or 5 k. The same logic in a groovyc-made class file would be 4 or 5 k, but groovyc-made AspectJ-woven files were 15 or 20 k. After decompiling with JAD, there'd be huge if/switch statements in the source.

 

If it's impractical to use external bytecode-level AOP with Groovy-made classes, will Groovy instead eventually support all AOP features currently available in existing tools?

 

Cheers, Gavin Grover

Reply | Threaded
Open this post in threaded view
|

Re: Groovy and AOP

Jochen Theodorou
Hi gavin,

Gavin Grover schrieb:
>
> Hi Groovy developers
>
> I've a question about how many AOP features does, and will, Groovy
> support. I realise the coming MOP will have some, have read about
> intercepting method calls and property accesses, and injecting into
> Expando, but can't find any more specifics.

first we should make a difference between bytecode based AOP and runtime
based AOP. The only way in normal Java to support AOP is the bytecode
based approach. Groovy on the otherside comes with some runtime based
AOP features. The downside is, that these runtime based features are
only available when a method call or anything else is made from Groovy
Code. A call from the Java side is always without the MetaClass.

What will be supported by Groovy then? accessing fields/properties,
invoking methods. But as I said, only if the call is made through the
MetaClass. Things like Methodentering are not directly supported. You
can simulate it by using Proxies, but that is not the same thing as
AspectJ allows you.

> About 18 months ago, I tried using AspectJ with classes compiled with
> Groovy beta 9 or 10. I've long lost the files, but remember a few points
> re why I gave it up.
>
> Your design goal is that groovyc-made classes can be RUN by Java as if
> they were javac-made (except for GroovyObject as the base class),

yes, that is difficult enough for the moment ;)

[...]
> (4)You couldn't weave into Closures, not knowing the names of them
> beforehand (eg, MyClass_closure3_closure7).

it is the same with annonymous inner classes, or not?

[...]
> I also remember file size bloat. If a javac-made class file was 3k, when
> AspectJ-woven it would be 4 or 5 k. The same logic in a groovyc-made
> class file would be 4 or 5 k, but groovyc-made AspectJ-woven files were
> 15 or 20 k. After decompiling with JAD, there'd be huge if/switch
> statements in the source.

ah yes? strange.

> If it's impractical to use external bytecode-level AOP with Groovy-made
> classes, will Groovy instead eventually support all AOP features
> currently available in existing tools?

No, I don't think all. Maybe we could start an extension to AspectJ, to
tell AspectJ how to handle groovyc compiled bytecode. should be the most
difficult thing in the world. But that requires someone how knows
AspectJ internals very good.

Another possibility would be to write an Groovyc extension, the
mechanism for that is basically available in the compiler. The Problem
here is setting and getting fields. that is not always done through
direct bytecode, it may be done by the MetaClass too.

bye blackdrag

--
Jochen Theodorou
Groovy Tech Lead

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Groovy and AOP

Gavin Grover
In reply to this post by Gavin Grover
> ========Jochen wrote:
> What will be supported by Groovy then? accessing fields/properties,
> invoking methods. But as I said, only if the call is made through the
> MetaClass.

Will it be possible to inject an interface onto an existing class, or change the base class for an existing object (eg, change java.util.List’s base class from Object to GroovyObject, so we can use MOP features on it from within Groovy) ?
> > (4)You couldn't weave into Closures, not knowing the names of them
> > beforehand (eg, MyClass_closure3_closure7).

> it is the same with annonymous inner classes, or not?

I’m sure it is. It would probably be possible to specify all closures or all anon inner classes for a particular enclosing class.

> first we should make a difference between bytecode based AOP and runtime
> based AOP. [...] Groovy on the otherside comes with some runtime based
> AOP features. [...]
> Maybe we could start an extension to AspectJ, to
> tell AspectJ how to handle groovyc compiled bytecode. [...]
> Another possibility would be to write an Groovyc extension, the
> mechanism for that is basically available in the compiler. The Problem
> here is setting and getting fields. that is not always done through
> direct bytecode, it may be done by the MetaClass too.

I’d say it would be easiest to do everything AOP in Groovy thru the MOP, at the same conceptual level as the scripting code, and not use any bytecode-level stuff at all.

> > If it's impractical to use external bytecode-level AOP with Groovy-made
> > classes, will Groovy instead eventually support all AOP features
> > currently available in existing tools?

> No, I don't think all.

The main AOP feature I’m thinking of is specifying classes, interfaces, methods, properties, and fields using pointcuts. So we could intercept all calls to, say, public and protected methods of all classes in a certain group of packages. Does the MOP allow this, or does the invokeMethod() have to be specified individually for each class?

> Things like Methodentering are not directly supported. You
> can simulate it by using Proxies, but that is not the same thing as
> AspectJ allows you.

If I want to set up the Observer pattern in the “more readable” AOP style, I’d need to introduce extra methods to the class. All the patterns in the Gamma et al book have been modelled in AspectJ. I'd hope to be able to do the same in Groovy, but much more tersely.

 

Cheers, Gavin Grover

 
Reply | Threaded
Open this post in threaded view
|

Re: Re: Groovy and AOP

Jochen Theodorou
Gavin Grover schrieb:

>
>  > ========Jochen wrote:
>  > What will be supported by Groovy then? accessing fields/properties,
>  > invoking methods. But as I said, only if the call is made through the
>  > MetaClass.
>
> Will it be possible to inject an interface onto an existing class, or
> change the base class for an existing object (eg, change
> java.util.List’s base class from Object to GroovyObject, so we can use
> MOP features on it >from within Groovy) ?

these are bytecode related things and not directly supported through
groovy. Of course we could think about a mechanism to add this to the
compiler, but precompiled groovy classes wouldn't be affected then.

[...]

>  > first we should make a difference between bytecode based AOP and runtime
>  > based AOP. [...] Groovy on the otherside comes with some runtime based
>  > AOP features. [...]
>  > Maybe we could start an extension to AspectJ, to
>  > tell AspectJ how to handle groovyc compiled bytecode. [...]
>  > Another possibility would be to write an Groovyc extension, the
>  > mechanism for that is basically available in the compiler. The Problem
>  > here is setting and getting fields. that is not always done through
>  > direct bytecode, it may be done by the MetaClass too.
>
> I’d say it would be easiest to do everything AOP in Groovy thru the MOP,
> at the same conceptual level as the scripting code, and not use any
> bytecode-level stuff at all.

As I said, as long as the things go through the MOP it is fine to log
entry/exit of methods, to react to accessing fields/properties. But
things like changing the baseclass is not doable with our MOP. Even with
the new one not.

>  > > If it's impractical to use external bytecode-level AOP with
> Groovy-made
>  > > classes, will Groovy instead eventually support all AOP features
>  > > currently available in existing tools?
>
>  > No, I don't think all.
>
> The main AOP feature I’m thinking of is specifying classes, interfaces,
> methods, properties, and fields using pointcuts. So we could intercept
> all calls to, say, public and protected methods of all classes in a
> certain group of packages. Does the MOP allow this, or does the
> invokeMethod() have to be specified individually for each class?

hmm... on a per class basis the MOP allows that, but not on a per
package basis... But I think that would be easy to implement... well I
should say for pointcuts on other than classes and interfaces. Waht have
you in mind with classes and interfaces?

>  > Things like Methodentering are not directly supported. You
>  > can simulate it by using Proxies, but that is not the same thing as
>  > AspectJ allows you.

I should correct myself. Of course this is supported ;)

> If I want to set up the Observer pattern in the “more readable” AOP
> style, I’d need to introduce extra methods to the class. All the
> patterns in the Gamma et al book have been modelled in AspectJ. I'd hope
> to be able to do the same in Groovy, but much more tersely.

The problem is, I only know the old AspectJ from some years ago, and I
was never into aspects, so I naturally don't know much about these
things. Ok, I know the basics, but that is all. So I am not usre what
book you are talking about ;) I doubt, that the MOP is able to support
all of the aspect features, but maybe most of them. Saying more requires
a bigger analyze

bye blackdrag

--
Jochen Theodorou
Groovy Tech Lead

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Re: Groovy and AOP

graemer
In reply to this post by Gavin Grover
On 7/26/06, Gavin Grover <[hidden email]> wrote:

>
>
> > ========Jochen wrote:
> > What will be supported by Groovy then? accessing fields/properties,
> > invoking methods. But as I said, only if the call is made through the
> > MetaClass.
>
> Will it be possible to inject an interface onto an existing class, or change
> the base class for an existing object (eg, change java.util.List's base
> class from Object to GroovyObject, so we can use MOP features on it from
> within Groovy) ?

MOP features can be used whether the object implements GroovyObject or
not. I'm not sure it will be possible to make an object implement an
interface or extend another class, but as Groovy allows you to omit
the type you could use MOP to implement the interface and then invoke
it without the type I imagine.

>
> > > (4)You couldn't weave into Closures, not knowing the names of them
> > > beforehand (eg, MyClass_closure3_closure7).
>
> > it is the same with annonymous inner classes, or not?
>
> I'm sure it is. It would probably be possible to specify all closures or all
> anon inner classes for a particular enclosing class.
>
>
> > first we should make a difference between bytecode based AOP and runtime
> > based AOP. [...] Groovy on the otherside comes with some runtime based
> > AOP features. [...]
>
> > Maybe we could start an extension to AspectJ, to
> > tell AspectJ how to handle groovyc compiled bytecode. [...]
>
> > Another possibility would be to write an Groovyc extension, the
> > mechanism for that is basically available in the compiler. The Problem
> > here is setting and getting fields. that is not always done through
> > direct bytecode, it may be done by the MetaClass too.
>
> I'd say it would be easiest to do everything AOP in Groovy thru the MOP, at
> the same conceptual level as the scripting code, and not use any
> bytecode-level stuff at all.
>
>
> > > If it's impractical to use external bytecode-level AOP with Groovy-made
> > > classes, will Groovy instead eventually support all AOP features
> > > currently available in existing tools?
>
> > No, I don't think all.
>
> The main AOP feature I'm thinking of is specifying classes, interfaces,
> methods, properties, and fields using pointcuts. So we could intercept all
> calls to, say, public and protected methods of all classes in a certain
> group of packages. Does the MOP allow this, or does the invokeMethod() have
> to be specified individually for each class?

This is something we're planning on implementing in Grails with
Grails-AOP. A pointcut mechanism that probably uses a builder syntax
or closures to provide this level of flexibility. It is still in the
planning phase at the moment.

Graeme

>
>
> > Things like Methodentering are not directly supported. You
> > can simulate it by using Proxies, but that is not the same thing as
> > AspectJ allows you.
>
> If I want to set up the Observer pattern in the "more readable" AOP style,
> I'd need to introduce extra methods to the class. All the patterns in the
> Gamma et al book have been modelled in AspectJ. I'd hope to be able to do
> the same in Groovy, but much more tersely.
>
>
>
> Cheers, Gavin Grover
>

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Re: Groovy and AOP

tugwilson
In reply to this post by Gavin Grover

On 26 Jul 2006, at 13:51, Gavin Grover wrote:

>
> The main AOP feature I’m thinking of is specifying classes,  
> interfaces, methods, properties, and fields using pointcuts. So we  
> could intercept all calls to, say, public and protected methods of  
> all classes in a certain group of packages. Does the MOP allow  
> this, or does the invokeMethod() have to be specified individually  
> for each class?


To do this you would need to hack MetaClassRegistry so that you could  
catch the creation of MetaClasses for the classes you are interested  
in. You would then wrap the MetaClass in something which intercepted  
whatever you needed and did what you wanted.

At the moment we don't have a hook to do that but it would be very  
easy to add one.

I actually did something similar when I was helping Mutual find a  
performance problem. I  that case, rather than mess with the  
MetaClassRegistry I automatically generated custom MetaClasses for  
all the classes in particular packages which wrapped the "real"  
MetaClasses. That was a bit of a kludge and hooking into the registry  
is better.


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: Groovy and AOP

Gavin Grover
In reply to this post by Jochen Theodorou
 
> > (2)The "execution" pointcut didn't work because the method calls from

> > groovyc-made code redirected the call thru "invokeMethod" in code

> > not controlled by AspectJ.

 

Whoops! I should've said the "call" pointcut didn't work for this reason, so had to use the "execution" instead.

 

> > The main AOP feature I'm thinking of is specifying classes, interfaces,
> > methods, properties, and fields using pointcuts. So we could intercept all
> > calls to, say, public and protected methods of all classes in a certain
> > group of packages. Does the MOP allow this, or does the invokeMethod() have
> > to be specified individually for each class?

Jochen Theodorou wrote:

> hmm... on a per class basis the MOP allows that, but not on a per
> package basis... But I think that would be easy to implement... well I
> should say for pointcuts on other than classes and interfaces. Waht have
> you in mind with classes and interfaces?
 
What I mean is using the names of classes/interfaces to be more specific about the methods/properties/fields to intercept, eg, the add(int,Object[]) method of all classes ending in "Adapter" in package "trep"
 
John Wilson wrote:
> To do this you would need to hack MetaClassRegistry so that you could  
> catch the creation of MetaClasses for the classes you are interested  
> in. You would then wrap the MetaClass in something which intercepted  
> whatever you needed and did what you wanted.
> At the moment we don't have a hook to do that but it would be very  
> easy to add one.
> I actually did something similar when I was helping Mutual find a  
> performance problem. I  that case, rather than mess with the  
> MetaClassRegistry I automatically generated custom MetaClasses for  
> all the classes in particular packages which wrapped the "real"  
> MetaClasses. That was a bit of a kludge and hooking into the registry  
> is better.
Graham Rocher wrote:
> This is something we're planning on implementing in Grails with
> Grails-AOP. A pointcut mechanism that probably uses a builder syntax
> or closures to provide this level of flexibility. It is still in the
> planning phase at the moment.
Pointcuts is a feature Groovy users, not using Grails, would also want.
 
You'll have fun designing the best way to specify pointcuts.
 
 
Cheers, Gavin Grover
 
Reply | Threaded
Open this post in threaded view
|

Re: Groovy and AOP

Gavin Grover
In reply to this post by Gavin Grover
> > Will it be possible to inject an interface onto an existing class, or change
> > the base class for an existing object (eg, change java.util.List's base
> > class from Object to GroovyObject, so we can use MOP features on it from
> > within Groovy) ?
 
Graham Rocher wrote:
> MOP features can be used whether the object implements GroovyObject or
> not. I'm not sure it will be possible to make an object implement an
> interface or extend another class, but as Groovy allows you to omit
> the type you could use MOP to implement the interface and then invoke
> it without the type I imagine.
 
As an example, with GroovyObjects I can use the MOP:
  class MyClass{
    def invokeMethod(String theName, Object theArgs){
      println "do nifty stuff with: $theName, $theArgs"
    }
  }
  c= new MyClass()
  c.backwards() //prints: do nifty stuff with: backwards, {}

But if I want to do the same with javac-compiled class, but called from Groovy, I get a groovy.lang.MissingMethodException:
  class MyCategory{
    static ArrayList invokeMethod(ArrayList list,
                                  String theName,
                                  Object theArgs){
      println "do nifty stuff with: $theName, $theArgs"
    }
  }
  use(MyCategory.class){
    rev= ['t',2,'s',7].backwards()
    println rev
  }
 
Not sure what you mean by "you could use MOP to implement the interface and then invoke it without the type". Anything typing tricks I try give a ClassCastException.
 
Cheers, Gavin Grover
Reply | Threaded
Open this post in threaded view
|

Re: Groovy and AOP

tugwilson

On 27 Jul 2006, at 02:14, Gavin Grover wrote:

>
> As an example, with GroovyObjects I can use the MOP:
>   class MyClass{
>     def invokeMethod(String theName, Object theArgs){
>       println "do nifty stuff with: $theName, $theArgs"
>     }
>   }
>   c= new MyClass()
>   c.backwards() //prints: do nifty stuff with: backwards, {}
>
> But if I want to do the same with javac-compiled class, but called  
> from Groovy, I get a groovy.lang.MissingMethodException:
>   class MyCategory{
>     static ArrayList invokeMethod(ArrayList list,
>                                   String theName,
>                                   Object theArgs){
>       println "do nifty stuff with: $theName, $theArgs"
>     }
>   }
>   use(MyCategory.class){
>     rev= ['t',2,'s',7].backwards()
>     println rev
>   }
>


This is not the way to do this.

Categories do not and will not allow you to override the MOP methods.  
(invokeMethod is a method on the MetaClass not on the class).

If you want to get at the invokeMethod for the MetaClass fo an  
ArrayList then you need to wrap the appropriate MetaClass in the  
MetaClass registry.


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email