Archive

Posts Tagged ‘Controller’

JSON conversion and request thread reuse

December 18th, 2009

Wrapping up (I hope) my experience with custom JSON conversions in Grails… The day before we were supposed to hit a major release milestone last week, I finally caught sight of a random bug that had been driving us nuts. For some AJAX requests, seemingly at random, the object that has the transient properties was not being rendered with them. Instead, it had only the regular, persistent properties and full representations of its associated objects rather than just the normal stubs of related objects with just the type and id. In other words, it was using deep JSON rendering, and this was overriding the custom JSON ObjectMarshaller that we had set for the class. But why was it doing it seemingly at random? This is where luck and experience combined to make the solution clear rather quickly and avoided some painful slogging through request handling on the server.

The luck part was that I remembered seeing a checkin from a teammate a couple of weeks ago where he got rid of direct use of a grails.converters.deep.JSON object (which is deprecated) and instead switched to a normal grails.converters.JSON object with a use('deep') statement:

def get = {
def o = OurClass.get(params.id);
JSON.use("deep")
render(contentType: "application/json", text: o as JSON)
}

This change was in a different controller for a different domain object though. Why was it affecting our other domain class? That’s where the experience part came in. A few years ago I had to track down why hibernate transactions would fail seemingly at random in another web app when running under JBoss. I could see why an initial transaction would fail (we’d get a timeout and not rollback properly), but there was no reason why later requests would cause failures. That’s when I discovered the downside of request thread pooling. Under most web contains, HTTP requests are handled by a pool of reusable threads. That means changes to thread local variables stick around between requests unless explicitly reset. In the case of the Hibernate bug, since the session was not getting closed properly, it wasn’t getting fully reset and cleared out, so subsequent requests that used that thread were getting the old session and failing because there was no way to get it back to a good state.

For the current JSON conversion bug, the JSON.use method was calling ConvertersConfigurationHolder.setTheadLocalConverterConfiguration(...), thus making the deep converter stick around for that thread. So when future requests came in to any controller on that thread, all JSON conversion calls were made with the deep configuration.

The solution is straightforward. Use the JSON.use(String, Closure) call instead when you want to make a deep call:

def get = {
def o = OurClass.get(params.id);
JSON.use("deep") {
render(contentType: "application/json", text: o as JSON)
}
}

This sets the configuration only for the closure, saving you from thread-based side effects later on.

Uncategorized , , ,

ControllerUnitTestCase: Documentation Has Arrived

November 19th, 2009

My team started on our first Grails app back in mid-August.  I set out to provide good examples of using the new testing features in Grails 1.1 to encourage the rest of the team.  Domain class testing went great, as did Service testing.  Unfortunately, there wasn’t any documentation on the ControllerUnitTestCase class in the Grails User Guide, and I couldn’t find any blog or forum posts to help out.  I tried creating an instance of it and tossing in a call to mockController(), but I didn’t get very far.  I had to shift focus to other tasks before I could dive into the source code itself and figure out what it did, so progress stopped for a while.

Fast forward to today when I finally had a strong need for a controller unit test setup.  I dove into the code and realized three things very quickly:

  1. You don’t need to call mockController().  It does that for you based on the name of the test class itself.
  2. You don’t want to call the constructor of your controller class in the test cases.  Use the newInstance() method instead so that all the proper scaffolding is put in place.
  3. You don’t even have to call newInstance() most of the time because the setUp() method inits a controller variable for you already.

Doh!  I wish I had taken 15 minutes back in August to look at the source.  It would have saved quite a bit of time by encouraging us to get proper controller test cases in place faster.

To add insult to injury, after spending that time and more getting some test cases just right, I decided to try a search for more documentation online again.   This time there was an answer to my query for help.  A post to the grails-user mailing list less than a month ago generated several responses with useful info, including Scott Davis posting about the most recent addition to his Mastering Grails series which was published just days before the post.

So nine months after the release of Grails 1.1 there is now good documentation on this great piece.  Many thanks to those who pulled it together.

Uncategorized , ,