Aspect (-like) closure function

In Grails (at least until the current version 2.2), taglibs are closures. For some taglib closures, I would like to use some “around” advice or wrap the closure in the interceptor.

In other words, let's say this is taglib directly from a Grails document:

class SimpleTagLib { def emoticon = { attrs, body -> out << body() << (attrs.happy == 'true' ? " :-)" : " :-(") } } 

Now, without changing the taglib code, I would like to indicate how long the "emoticon" will take.

Spring AOP (and all the other AOP I can find) seems to work only on Java methods - and taglib is always based on closure. A “roundabout” pointcut would be ideal for this, but I cannot figure out how to make it work.

+4
source share
1 answer

I wrote something similar, which I put as a public closure in category I, then connected to the services:

 // TimingCategory.groovy /** * Provides common AOP timing functionality to Services which mixin this category. */ class TimingCategory { static Closure timer = { String label = "The call", Closure closure -> Long start = System.currentTimeMillis() def result = closure.call() Long end = System.currentTimeMillis() Long duration = end - start log.warn "${label} took ${duration} ms" return result } } 

In other classes, you simply refer to closing the timer as such:

 @Mixin(TimingCategory) public class WhateverService { public String doSomeWork() { timer "Doing a lot of work", { 1000.times { doSomething() } someMethodWithAStringReturnValue() } } } 

This will give you the output of the "WARN: A lot of work took nn ms to complete" log and return the value of the internal closure as the return value of the doSomeWork method.

For your taglib instance, simply wrap out << ... in

 timer "Writing an emoticon", { // your code } 

code.

If you do not need to pass an internal return value, you can instead return the duration as a result of a close call.

Update

Perhaps I misunderstood - you ask how to terminate taglib without changing the taglib code? How about creating a custom taglib that takes a body and passes it to other tags for execution?

I have not tried this, but something like:

 class TimedTagLib { static namespace = "timer" def timedTag = { attrs, body -> timer "Executing the timed tag", { out << body() } } } 

And calling him like

 <timer:timedTag><g:emoticon whatever="something">Text</g:emoticon></timer:timedTag> 

Update 2:

Ok, so I tried. Works great. My last code (I added a second timer closure that returns a duration):

 // TimedTagLib.groovy @Mixin(TimingCategory) class TimedTagLib { static namespace = "timer" def timedTag = { attrs, body -> def duration = returnTimer "Printing the timed tag", { out << body() } out << "Took ${duration} ms to print" } } 

And the view:

 // someView.gsp <timer:timedTag> <g:formatLocalDate date="${LocalDate.now()}" /> </timer:timedTag> 

Final HTML:

 03/19/2013 Took 6 ms to print 

And he also wrote a magazine.

+1
source

All Articles