Jun 11, 2013

A Tale From the Grails trenches: Nasty 1.3.X Bug

grails_icon

Note: If this post help just one other person avoid the daylong head scratching session I recently went through It will be worth it.

It all starts early on a Monday moring. Just as I’m sitting down to start on what I had ‘planned’ to work on that day, my technical manager comes over and merely says to me:

Page XYZ was throwing errors all weekend.

bounce the server and it seems to be fixed, but can you look into it?

At this point 3 things go through my mind:

  1. There had not been any new code deployed to Production in over 3 weeks.
  2. It’s never a good sign when cycling a production server is the solution to any problem
  3. I need to stop being the first developer in on Mondays 🙂

After a half hour of looking at log files and trying to reproduce it on my local machine I came across this error:

org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException: Tag [render]   is missing required attribute [template]

at com.bug.TestController$_closure2.doCall(TestController.groovy:12)

at com.bug.TestController$_closure2.doCall(TestController.groovy)

at java.lang.Thread.run(Thread.java:680)

This was very odd to me. Why was a GrailsTagException being thrown from my Contrller class? I know that you can invoke the GrailsTagLibs in a controller via the g attribute that gets injected, but my code was NOT using that.

Here is the code that was throwing the error:

try{
    def result = doSomething()
    render result as JSON
} catch(Exception ex) {
    def error = [error: 'There was an error""]
    render error as JSON, status: 503
}

Can you spot the error? Let’s look closely at this line in the catch block:

render error as JSON, status: 503

The render method on controllers have 2 main method signatures that you can use, one that takes a single param that can be something that you can write to the response like a simple string, or XML, or JSON. Another is one that takes a map, that can include: text, status, contentType, template, etc, all of which is marked as optional [render doc]

But our error message is saying that the template attribute is required?

If you look closely our suspect line of code above is trying to call a render method with as signature of:

render(JsonConverter, LinkedHashMap)

and this does not exist. So because this method does not exist, and we have all the power of Groovy at our disposal; the magic of method missing comes in to play and tries to go find a render method to match this description. Finally it comes to the g.render() method that is available via the GrailsTagLib.

Boom! This is where things go badly

Once Grails finds the render method on the Grails Tag Lib, which is a completly separate chunk of code from the controller render method, it then binds the TagLib render to ALL future calls to render on EVERY controller.

And because the template attribute is required in the Tag Lib version of render any call to render on any controller that dosn’t pass in a ‘template’ attribute will die a fiery death with a GrailsTagException.

The good news it that this bug has been addressed in Grails 2.x and above. I hope you never have to experience this one yourself but if you are stuck on the 1.3.x branch and do, I hope this post servers you well.

Here is a sample project that reproduces this issue in Grails 1.3.9 GitHub

 

About the Author

Object Partners profile.

One thought on “A Tale From the Grails trenches: Nasty 1.3.X Bug

  1. mike says:

    Thanks for sharing!

    1. Zan Thrash says:

      Lauri H

      The project I was on at the time was a fairly large multi-app system where the ROI on upgrading to 2.x was not there for the business.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Using Conftest to Validate Configuration Files
Conftest is a utility within the Open Policy Agent ecosystem that helps simplify writing validation tests against configuration files. In a previous blog post, I wrote about using the Open Policy Agent utility directly to […]
SwiftGen with Image & Color Asset Catalogs
You might remember back in 2015 when iOS 9 was introduced, and we were finally given a way to manage all of our assets in one place with Asset Catalogs. A few years later, support […]
Tracking Original URL Through Authentication
If you read my other post about refreshing AWS tokens, then you probably have a use case for keeping track of the original requested resource while the user goes through authentication so you can route […]
Using Spring Beans in a Kafka Streams ExceptionHandler
There are many things to know before diving into Kafka Streams. If you haven’t already, check out these 5 things as a starting point. Bullet 2 mentions designing for exceptions. Ironically, this seems to be […]