I'm trying to understand tracing via invokeMethod, and I'm having behavior I don't understand.
In the code (included at the end, ripped of unashamedly from GINA) I have a closure and a
method that both call another method 'outer', which calls 'inner'. I expected them both to show
tracing for both outer and inner, but only the method does. The closure traces the inner
method, but not the outer.
What is it that I'm completely failing to understand?
I'm using Groovy 1.5.6
The larger task I'm trying to accomplish is to be able to use the excellent
runtimeLogging plugin to allow me to turn on tracing on-the-fly for my Grails app.
What I want is a superclass that I can use for controllers as well as some
files in the /src directory to have all the code in one place. That is, I can
subclass my controllers as well as other classes and get detailed tracing all
at once. It seems to be working reasonably well, except for this issue. If there
are other ways to make this work, I'd be happy to use them instead <G>.
But this issue seems to be a pure Groovy issue that's at the heart of my
problem.
Thanks
Erick
************program output
Entering shouldTraceOuterAndInnerClosure
Entering inner
Leaving inner
Leaving shouldTraceOuterAndInnerClosure
Entering shouldTraceOuterAndInnerMethod
Entering outer
Entering inner
Leaving inner
Leaving outer
Leaving shouldTraceOuterAndInnerMethod
*************end program output
****************code starts
import org.codehaus.groovy.runtime.StringBufferWriter
import org.codehaus.groovy.runtime.InvokerHelper
class Traceable implements GroovyInterceptable {
private static int indent = 1
Writer writer = new PrintWriter(System.out)
Object invokeMethod(String name, Object args) {
def result
def metaClass = InvokerHelper.getMetaClass(this)
writer.write("\n" + ' ' * indent + "Entering $name")
++indent
result = metaClass.invokeMethod(this, name, args)
--indent
writer.write("\n" + ' ' * indent + "Leaving $name")
return result
}
}
class Whatever extends Traceable {
int outer() {
return inner()
}
int inner() {
return 1
}
def shouldTraceOuterAndInnerClosure = {
return outer()
}
int shouldTraceOuterAndInnerMethod() {
return outer()
}
}
def log = new StringBuffer()
def traceMe = new Whatever(writer : new StringBufferWriter(log))
traceMe.shouldTraceOuterAndInnerClosure()
traceMe.shouldTraceOuterAndInnerMethod()
println log.toString()
*****************program ends**************