Grails reminds me of those Anton Chekov stories I used to enjoy. A lot of fun, but tough to remember the plethora of characters introduced at different parts of the story, in the case of grails, it is methods added via meta-programming. Each of these methods add an important functionality, but it is tough to guess where the implementation source is and where this method was added.

For example we know every domain class has a list method, but where is it added to the domain class and which class actually backs the list method implementation. If we had information about where it was added in this case HibernateGrailsPlugin, a quick browse through the source would let us know that ListWithFilterMethod is our points of interest.

So I wanted something that for a domain class would give me method listings, with the one for list like


list

public static Object list()
Added by HibernatePluginSupport$_addQueryMethods_closure44

This tells me that list method is added by addQueryMethod of HibernateGrailsPlugin. I can easily find from the source then that ListWithFilterMethod provides the list implementation. The next step is to add a controller and some ui which would help me show such information about any class (Domain, Controller or any other groovy class). The class name could be passed as a request parameter, the ui could be made via jquery so that this fits in as an additional floating div over my existing ui.

Thanks to the simplicity of grails, all this controller has to do is :

  1. Load the class from the parameter name, get its meta data
  2. Iterate through the meta methods, collecting the source from the closure or cached method declaring class and pass it to the ui as json.

The code for doing this could be something like

def metaClass =GrailsUtil.getMetaClass(params.clazzName)
metaClass?.getMethods().each{
    if (it instanceof ClosureStaticMetaMethod) {
       list.add(new MethodInfo(it.name, it.closure.class.simpleName, extractMethodName(it)))
    } else if (it instanceof ClosureMetaMethod) {
       list.add(new MethodInfo(it.name, it.doCall?.cachedMethod?.declaringClass.simpleName, extractMethodName(it)))
    } else {
       list.add(new MethodInfo(it.toString(), null, null))
    }
}
list.sort()
render list as JSON


The end result looks something like

MethodInfo

I call it EGDoc, added it as a floating layer so that it does not come in the way of normal functioning of the application, of course is enabled when the environment is development.