Grails and Spring AOP

View: New views
10 Messages — Rating Filter:   Alert me  

Grails and Spring AOP

by matthias_k :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I am desperately trying to make Spring AOP work in my Grails project. I define
an advice on a service method, which works fine, but as soon as the pointcut
matches and the advice is executed, Grails throws an exception:

"java.lang.IllegalArgumentException: object is not an instance of declaring
class"

I guess this has something to do with Groovy and meta objects? Not sure.

Since I have seen Graeme saying on this mailing list that Spring AOP works just
fine in Grails, I am wondering what I am doing wrong.

Thanks,
Matthias

PS:
Here is my resources.xml, it's just for testing purposes right now (MyAspect is
annotated with @Aspect and defines a public method "foo"):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">          
             
    <aop:config>
       
      <aop:aspect id="theAspect" ref="testAspect">
   
        <aop:pointcut id="exec"
              expression="execution(* org.myapp.services.MyService.*(..))" />
             
        <aop:before pointcut-ref="exec" method="foo" />
       
      </aop:aspect>
   
    </aop:config>
   
    <bean id="testAspect" class="org.myapp.MyAspect">
    </bean>
   
</beans>


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

    http://xircles.codehaus.org/manage_email



Re: Grails and Spring AOP

by fernando.takai :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I had this kind of problem (object is not an instance of declaring
class) when trying to use Java + Groovy. My solution was creating an interface and implementing it on the Service. Then, i used the interface where should be the service.

On Tue, Sep 23, 2008 at 1:26 PM, Matthias <m.kaeppler@...> wrote:
Hi,

I am desperately trying to make Spring AOP work in my Grails project. I define
an advice on a service method, which works fine, but as soon as the pointcut
matches and the advice is executed, Grails throws an exception:

"java.lang.IllegalArgumentException: object is not an instance of declaring
class"

I guess this has something to do with Groovy and meta objects? Not sure.

Since I have seen Graeme saying on this mailing list that Spring AOP works just
fine in Grails, I am wondering what I am doing wrong.

Thanks,
Matthias

PS:
Here is my resources.xml, it's just for testing purposes right now (MyAspect is
annotated with @Aspect and defines a public method "foo"):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

   <aop:config>

     <aop:aspect id="theAspect" ref="testAspect">

       <aop:pointcut id="exec"
             expression="execution(* org.myapp.services.MyService.*(..))" />

       <aop:before pointcut-ref="exec" method="foo" />

     </aop:aspect>

   </aop:config>

   <bean id="testAspect" class="org.myapp.MyAspect">
   </bean>

</beans>


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

   http://xircles.codehaus.org/manage_email





--
Fernando "Takai"
http://flickr.com/photos/supeertakai
http://fernandotakai.wordpress.com
http://fernandotakai.jaiku.com

Re: Grails and Spring AOP

by matthias_k :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Fernando Takai <fernando.takai <at> gmail.com> writes:

>
> I had this kind of problem (object is not an instance of declaring
> class) when trying to use Java + Groovy. My solution was creating an interface
and implementing it on the Service. Then, i used the interface where should be
the service.

I see, and did you try the same thing for Grails Controllers, too?

I tried to match a controller using a pointcut like this:

execution(* org.myapp.controllers.*Controller$_closure*.doCall(..))

but it won't match. It won't even match when supplying a concrete Controller
class and closure number, e.g. MyController$_closure1.

any ideas?

Thanks for your input.


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

    http://xircles.codehaus.org/manage_email



Re: Grails and Spring AOP

by matthias_k :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Matthias <m.kaeppler <at> gmail.com> writes:

>
> Hi,
>
> I am desperately trying to make Spring AOP work in my Grails project. I define
> an advice on a service method, which works fine, but as soon as the pointcut
> matches and the advice is executed, Grails throws an exception:
>
> "java.lang.IllegalArgumentException: object is not an instance of declaring
> class"
>
> [...]
>

Hi guys,

I still haven't solved this puzzle. Surely anyone has more experience with this
than I do?

Any help appreciated!

Best,
Matthias


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

    http://xircles.codehaus.org/manage_email



Re: Re: Grails and Spring AOP

by Rob Hunter :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
I had the same issue and resolved it by creating an interface which my class then implemented.

Regards

Rob
Matthias <m.kaeppler <at> gmail.com> writes:
  
Hi,

I am desperately trying to make Spring AOP work in my Grails project. I define
an advice on a service method, which works fine, but as soon as the pointcut 
matches and the advice is executed, Grails throws an exception:

"java.lang.IllegalArgumentException: object is not an instance of declaring
class"

[...]

    

Hi guys,

I still haven't solved this puzzle. Surely anyone has more experience with this
than I do?

Any help appreciated!

Best,
Matthias


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

    http://xircles.codehaus.org/manage_email


  


Re: Re: Grails and Spring AOP

by Peter Ledbrook-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I still haven't solved this puzzle. Surely anyone has more experience with this
> than I do?

Hi,

I'm not sure anyone has tried with AOP 2. Internally, Grails uses the
old AOP 1 style quite extensively, but I'm not sure the newer style
works with Groovy classes, and in particular closures. With the
Profiler Plugin for example, I used different interception techniques
- basically a mix of AOP 1, meta-programming, and a special closure
wrapper.

That said, it's been quite a while since I last looked at Spring's AOP
support and I can't remember how the AOP 2 style works at all, sorry.

Peter

--
Software Engineer
G2One, Inc.
http://www.g2one.com/

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

    http://xircles.codehaus.org/manage_email



Re: Grails and Spring AOP

by matthias_k :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Robert,

Robert Hunter <robert.hunter <at> patersons.net> writes:
>
>
> I had the same issue and resolved it by creating an
> interface which my class then implemented.

yes, that's what Fernando suggested earlier in this thread, but that does not
work with Grails Controllers, because those are based on closures -- unless
of course I would only use the closures as wrappers around the interface
methods and apply any advice to the latter, e.g.:

class MyController implements MyInterface {

   // the controller closure called from a Web client
   def foo = {
       // only redirect -- aspect would match this call I guess?
       fooFromInterface()
   }

   public void fooFromInterface() {
       // perform actual controller logic
   }

}

not sure if this works... btw, will some closure "foo" name-clash with a public
method foo() from an interface?

Best,
Matthias


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

    http://xircles.codehaus.org/manage_email



Re: Grails and Spring AOP

by matthias_k :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Guys,

I have got it working, somehow, but it involves a workaround which I am not
happy with. First, two things seem to be required in order for advice being
applied to an object in Grails:

1) As has been said before, it must be of the same type that is referenced in
the aspect declaration, otherwise an "instance is not of declaring type" error
is thrown. This can be solved by implementing an interface and match the
pointcut against that interface.

2) The object that is being advised must be a Spring bean, i.e. it must be
managed by the container. This is not true for Grails Controllers, and this
is the reason why I was able to apply advice to my services, but not to my
controllers.

Unfortunately, controllers are instantiated per-request and parameters
bound as such. So what I did was for each controller create an interface
and an implementation of that interface, to which the controller closures
forward, e.g.:

interface Foo {
   def foo(def controller)
}

// this must be a managed bean
class FooImpl {
   def foo(def controller) {
       controller.flash.message = "advice applied!"
   }
}

class FooController {
   def impl // injected by spring

   def fooClosure = {
       // forward call
       impl.foo(this)
   }
}

Now any advice declared on Foo will match, however, this solution has many
drawbacks: Firstly, of course, another level of indirection is introduced,
with all the related drawbacks (performance, readability, ...)
Secondly, all controller logic is now moved to FooImpl, but FooImpl needs
access to "private" controller fields (e.g. params, flash, ...).
Given, right now there is no such thing as private fields or methods in
Groovy, but this may change with upcoming versions I guess and break
this workaround (unless there will be public getters for everything).
Lastly, every controller impl has to be declared manually as a bean.

So, does anyone have a better solution at hand, because I am not very
happy with this.

Thanks and best regards,
Matthias


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

    http://xircles.codehaus.org/manage_email



Re: Re: Grails and Spring AOP

by Scott Vlaminck :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'm also having problems with AOP in Grails 1.1. I can't seem to get
around advice working on a Grails Service. I get no error, but my
aspect is not invoked.

To simplify everything, I created a simple Hello World app that does
almost nothing: my controller calls my service and both print log
messages. The service implements an interface as described earlier in
this thread (the interface is defined in src/groovy) and my aspect
just logs before and after the method invocation (the aspect is
defined in grails-app/utils).

I've tried a number of different ways of configuring the aspect in
resources.groovy, but nothing seems to change (except I do get errors
on startup if I define the aspect incorrectly in resources.groovy).
I've even tried defining my Service and interface in the default
package and in their own package.

This is my first time using Spring AOP, so I must be missing something
simple. Any thoughts are very much appreciated. I uploaded my hello
world app to google code for anyone interested:
http://code.google.com/p/grails-aop-hello-world/

Also, the relevant bits of my app are included below in case someone
has any ideas.

Thanks,
Scott


Service:
------------------------------
public class TheService implements TheServiceInterface {
        def service(Integer i) {
                log.debug "TheService.service(${i})"
                println "TheService.service(${i})"
                return "Hello world"
        }
}
------------------------------


Aspect:
------------------------------
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class TheAspect implements MethodInterceptor {
    public Object invoke(MethodInvocation method) throws Throwable
        {
        log.debug("Before Invoking Method");
        println("Before Invoking Method");

        Object val = method.proceed();

        log.debug("After Invoking Method");
        println("After Invoking Method");

        return val + "updated value";
    }

 // not sure if this method is necessary or even doing anything
    public Object invoke(MethodInvocation method, Integer i) throws Throwable {
        log.debug("Before Invoking Method with ${i}");
        println("Before Invoking Method with ${i}");

        Object val = method.proceed();

        log.debug("After Invoking Method with ${i}");
        println("After Invoking Method with ${i}");

        return val + "updated value";
    }
}
------------------------------


I've tried a number of different config changes in resources.groovy
(one at a time). Below are two versions that seem like they should
each work.

conf/spring/resources.groovy:
------------------------------
theAspect(TheAspect)

// config version 1
aop {
        config {
                aspect(ref:"theAspect") {
                        pointcut id:"thePointcut", expression:"execution(*
TheServiceInterface.service(Integer)) && args(i)"
                        around 'pointcut-ref':"thePointcut", method:"invoke", 'arg-names':"i"
                }
        }
}

// config version 2
aop {
        config("proxy-target-class":true) {
                aspect(id:"theAspectId", ref:"theAspect" ) {
                        around method:"invoke", pointcut: "execution(*
TheServiceInterface.service(Integer)) && args(i)", 'arg-names':"i"
                }
        }
}
------------------------------




Again, any thoughts or pointers are appreciated. Thanks in advance.



-------------------------------------------------
Scott Vlaminck // scott@...
Refactr LLC // http://refactr.com
mobile // 612-386-9382
-------------------------------------------------



On Mon, Oct 20, 2008 at 6:08 AM, Matthias <m.kaeppler@...> wrote:

> Guys,
>
> I have got it working, somehow, but it involves a workaround which I am not
> happy with. First, two things seem to be required in order for advice being
> applied to an object in Grails:
>
> 1) As has been said before, it must be of the same type that is referenced in
> the aspect declaration, otherwise an "instance is not of declaring type" error
> is thrown. This can be solved by implementing an interface and match the
> pointcut against that interface.
>
> 2) The object that is being advised must be a Spring bean, i.e. it must be
> managed by the container. This is not true for Grails Controllers, and this
> is the reason why I was able to apply advice to my services, but not to my
> controllers.
>
> Unfortunately, controllers are instantiated per-request and parameters
> bound as such. So what I did was for each controller create an interface
> and an implementation of that interface, to which the controller closures
> forward, e.g.:
>
> interface Foo {
>   def foo(def controller)
> }
>
> // this must be a managed bean
> class FooImpl {
>   def foo(def controller) {
>       controller.flash.message = "advice applied!"
>   }
> }
>
> class FooController {
>   def impl // injected by spring
>
>   def fooClosure = {
>       // forward call
>       impl.foo(this)
>   }
> }
>
> Now any advice declared on Foo will match, however, this solution has many
> drawbacks: Firstly, of course, another level of indirection is introduced,
> with all the related drawbacks (performance, readability, ...)
> Secondly, all controller logic is now moved to FooImpl, but FooImpl needs
> access to "private" controller fields (e.g. params, flash, ...).
> Given, right now there is no such thing as private fields or methods in
> Groovy, but this may change with upcoming versions I guess and break
> this workaround (unless there will be public getters for everything).
> Lastly, every controller impl has to be declared manually as a bean.
>
> So, does anyone have a better solution at hand, because I am not very
> happy with this.
>
> Thanks and best regards,
> Matthias
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>

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

    http://xircles.codehaus.org/manage_email



Re: Re: Grails and Spring AOP

by Scott Vlaminck :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Following up on my own post: I was able to get AOP before, after, and
around advice working.

I've created an example app with tests and with a service that is
wrapped with around advice. It's hosted here for anyone else having
problems:

http://code.google.com/p/grails-aop-hello-world/source/checkout

I've also detailed my problems and solutions here:

http://refactr.com/blog/2009/05/problems-with-aop-in-grails-1-1/

http://refactr.com/blog/2009/06/success-with-aop-in-grails-11/


Hopefully it will help someone in the future.

Scott

-------------------------------------------------
Scott Vlaminck // scott@...
Refactr LLC // http://refactr.com
mobile // 612-386-9382
-------------------------------------------------



On Mon, May 11, 2009 at 8:50 AM, Scott Vlaminck <scott@...> wrote:

> I'm also having problems with AOP in Grails 1.1. I can't seem to get
> around advice working on a Grails Service. I get no error, but my
> aspect is not invoked.
>
> To simplify everything, I created a simple Hello World app that does
> almost nothing: my controller calls my service and both print log
> messages. The service implements an interface as described earlier in
> this thread (the interface is defined in src/groovy) and my aspect
> just logs before and after the method invocation (the aspect is
> defined in grails-app/utils).
>
> I've tried a number of different ways of configuring the aspect in
> resources.groovy, but nothing seems to change (except I do get errors
> on startup if I define the aspect incorrectly in resources.groovy).
> I've even tried defining my Service and interface in the default
> package and in their own package.
>
> This is my first time using Spring AOP, so I must be missing something
> simple. Any thoughts are very much appreciated. I uploaded my hello
> world app to google code for anyone interested:
> http://code.google.com/p/grails-aop-hello-world/
>
> Also, the relevant bits of my app are included below in case someone
> has any ideas.
>
> Thanks,
> Scott
>
>
> Service:
> ------------------------------
> public class TheService implements TheServiceInterface {
>        def service(Integer i) {
>                log.debug "TheService.service(${i})"
>                println "TheService.service(${i})"
>                return "Hello world"
>        }
> }
> ------------------------------
>
>
> Aspect:
> ------------------------------
> import org.aopalliance.intercept.MethodInterceptor;
> import org.aopalliance.intercept.MethodInvocation;
>
> public class TheAspect implements MethodInterceptor {
>    public Object invoke(MethodInvocation method) throws Throwable
>        {
>        log.debug("Before Invoking Method");
>        println("Before Invoking Method");
>
>        Object val = method.proceed();
>
>        log.debug("After Invoking Method");
>        println("After Invoking Method");
>
>        return val + "updated value";
>    }
>
>  // not sure if this method is necessary or even doing anything
>    public Object invoke(MethodInvocation method, Integer i) throws Throwable {
>        log.debug("Before Invoking Method with ${i}");
>        println("Before Invoking Method with ${i}");
>
>        Object val = method.proceed();
>
>        log.debug("After Invoking Method with ${i}");
>        println("After Invoking Method with ${i}");
>
>        return val + "updated value";
>    }
> }
> ------------------------------
>
>
> I've tried a number of different config changes in resources.groovy
> (one at a time). Below are two versions that seem like they should
> each work.
>
> conf/spring/resources.groovy:
> ------------------------------
> theAspect(TheAspect)
>
> // config version 1
> aop {
>        config {
>                aspect(ref:"theAspect") {
>                        pointcut id:"thePointcut", expression:"execution(*
> TheServiceInterface.service(Integer)) && args(i)"
>                        around 'pointcut-ref':"thePointcut", method:"invoke", 'arg-names':"i"
>                }
>        }
> }
>
> // config version 2
> aop {
>        config("proxy-target-class":true) {
>                aspect(id:"theAspectId", ref:"theAspect" ) {
>                        around method:"invoke", pointcut: "execution(*
> TheServiceInterface.service(Integer)) && args(i)", 'arg-names':"i"
>                }
>        }
> }
> ------------------------------
>
>
>
>
> Again, any thoughts or pointers are appreciated. Thanks in advance.
>
>
>
> -------------------------------------------------
> Scott Vlaminck // scott@...
> Refactr LLC // http://refactr.com
> mobile // 612-386-9382
> -------------------------------------------------
>
>
>
> On Mon, Oct 20, 2008 at 6:08 AM, Matthias <m.kaeppler@...> wrote:
>> Guys,
>>
>> I have got it working, somehow, but it involves a workaround which I am not
>> happy with. First, two things seem to be required in order for advice being
>> applied to an object in Grails:
>>
>> 1) As has been said before, it must be of the same type that is referenced in
>> the aspect declaration, otherwise an "instance is not of declaring type" error
>> is thrown. This can be solved by implementing an interface and match the
>> pointcut against that interface.
>>
>> 2) The object that is being advised must be a Spring bean, i.e. it must be
>> managed by the container. This is not true for Grails Controllers, and this
>> is the reason why I was able to apply advice to my services, but not to my
>> controllers.
>>
>> Unfortunately, controllers are instantiated per-request and parameters
>> bound as such. So what I did was for each controller create an interface
>> and an implementation of that interface, to which the controller closures
>> forward, e.g.:
>>
>> interface Foo {
>>   def foo(def controller)
>> }
>>
>> // this must be a managed bean
>> class FooImpl {
>>   def foo(def controller) {
>>       controller.flash.message = "advice applied!"
>>   }
>> }
>>
>> class FooController {
>>   def impl // injected by spring
>>
>>   def fooClosure = {
>>       // forward call
>>       impl.foo(this)
>>   }
>> }
>>
>> Now any advice declared on Foo will match, however, this solution has many
>> drawbacks: Firstly, of course, another level of indirection is introduced,
>> with all the related drawbacks (performance, readability, ...)
>> Secondly, all controller logic is now moved to FooImpl, but FooImpl needs
>> access to "private" controller fields (e.g. params, flash, ...).
>> Given, right now there is no such thing as private fields or methods in
>> Groovy, but this may change with upcoming versions I guess and break
>> this workaround (unless there will be public getters for everything).
>> Lastly, every controller impl has to be declared manually as a bean.
>>
>> So, does anyone have a better solution at hand, because I am not very
>> happy with this.
>>
>> Thanks and best regards,
>> Matthias
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>>    http://xircles.codehaus.org/manage_email
>>
>>
>>
>

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

    http://xircles.codehaus.org/manage_email