Monday, July 25, 2011

Grails, Camel and Hibernate session

It's been a while since I thought about manually opening Hibernate sessions to do some work on the database. The usual thing is simply to call one of the GORM methods like get() or save() and have the framework tackle all the bits and pieces regarding low-level Hibernate usage for me.

From time to time however it is important to have a high-level understanding of what's going on behind the scenes. One example of that is saving entities in services utilized as part of Camel routes. But let's start from the beginning...

In Grails opening Hibernate session is handled by a Spring class called OpenSessionInViewFilter. This is a filter that opens a Hibernate session before anything else is happening and closes it after the processing is done. With this filter in place a Hibernate session is available throughout the whole request cycle.

When doing processing in Camel we're in a separate thread completely outside the normal Grails request processing so there's nothing there to open the Hibernate session for us. As a side note one needs to remember that the same happens in pretty much every case where a separate thread is fired to do some processing. In all those cases Hibernate session is not available.

But I still want to use GORM in those places! How can I open a session manually?

Well, that's the easiest thing ever. GORM-managed entities expose a method called withNewSession that takes a closure with one parameter (the newly created session) and life is good again.
To make this more common I'll give you two other examples of such a method: withTransaction and withSession. The first one fires of a new transaction and closes it after the processing is done and the second one is kind of a utility that allows you to access the currently active Hibernate session if you find yourself in need doing so.

I hope this will save someone some time :)

4 comments:

Alex Anderson said...

Hi Matthias,

Great blog, and great plugin in grails-routing.

In the article, are you saying that normal GORM stuff won't work in a Grails service triggered by a Camel route? In my experience (with grails-routing 1.1 and Camel 2.5.x) it's OK - will I run into trouble if I upgrade to grails-routing 1.2.x?

Alex

Matthias Hryniszak said...

@Alex My advise is not to upgrade to 1.2.0. This has been the worse mistake I made so far when it comes to this plugin and I'll try to correct it as soon as I find some spare time. It's unpredictable what will happen - that's what I'm saying.

Alex Anderson said...

Hi Matthias,

How are things with grails-routing?

I did upgrade to 1.2.0 in the end, and having some "unpredictable" behaviour (as you predicted ;)) - we're seeing calls to SomeDomainObject.save() not honoured in Service methods called as beanRefs in Camel routes.

This is fixed by add flush:true to the save call, but would it be safer to wrap service method contents in withNewTransaction?

I'm just upgrading to grails-routing 1.2.2 to see if that helps, but from the code the only significant change seems to be bumping the Camel version to 2.9.2

Thanks for any pointers,

Alex

GrumpyMouseAdmin said...

Firstly thanks for the plugin its been a lifesaver and I am using it to poll for emails on a schedule, works brilliantly. My question which I hope you can answer is is it possible to have the schedule working on the route but also trigger the poll manually as well and how would I trigger it manually?