2

I have a Grails application (2.5.4) deployed on production which receives a large amounts of traffic.

We are getting intermittent LazyInitializationException exceptions when trying to access fields from domain objects that are stored in the session.

To clarify how the flow works:

We have a filter (http://docs.grails.org/2.5.4/ref/Plug-ins/filters.html) that gets called before each controller action. In this filter we store a domain object in the session (http://docs.grails.org/2.5.4/ref/Servlet%20API/session.html) like this:

session.account = Account.get(1)

In the controller, we retrieve the Domain like this:

def account = session.account

We then pass the domain object to another service, which calls another service which eventually tries to call a hasMany field on the domain object like this:

account.transactions.name

The above throws a LazyInitializationException with a message similar to this:

failed to lazily initialize a collection of role: com.example.app.Account.transactions, no session or session was closed

So for some reason the Hibernate session is being closed before the request is finished, hence the lazy load exception.

We found doing the following in the controller completely eliminates the error from occurring:

Account account = Account.findById(session.account.id)

The problem is, I have no idea why and would like to understand why this fixes the issue before blindly implementing this fix in other parts of the application. I see no reason why the object should become detached from the Hibernate Session as this flow is all occurring within the same request. On top of this, it is a very random problem - it occurs maybe 1% of the time the request is made, if not less.

To clarify, the question is; Why is the session being closed and why is the object becoming detached from the Hibernate Session when its all happening within the same request scope? Also, why it does it only happen very rarely and randomly?

DeaIss
  • 2,525
  • 7
  • 27
  • 37
  • Have you tried using `account.attach()` before trying to access `account.transactions`? See http://docs.grails.org/latest/ref/Domain%20Classes/attach.html – Emmanuel Rosa Dec 07 '16 at 21:51
  • Hey - I haven't specifically tried that but I would image it would work just as well as doing `Account account = Account.findById(session.account.id)`. My question is not how to re-attach the domain to the session as that is easy, but why its being detached in the first place. The documentation in the link you gave states: "If an object is retrieved from the Session and placed into a web scope such as the HttpSession it will be "detached" from the Hibernate Session once the Session is closed and discarded". So why is the session closed and discarded if the request has not finished? – DeaIss Dec 08 '16 at 10:37
  • Grails has a Slack channel where the gurus tend to hang out. StackOverflow is better for "How to..." questions, so I think you'll have better success at Slack or the Grails mailing list. – Emmanuel Rosa Dec 08 '16 at 23:52
  • Thanks - I've asked on the slack channel. I'll report back if I get a reply. – DeaIss Dec 09 '16 at 12:48

1 Answers1

0

Hello this happens because the lazy mode will cache only the first level of the domain, so when you try to access the other field will give you this error and the default fetch mode usually is lazy, I would keep like this and do as you are doing, Account account = Account.findById(session.account.id)

Because depending on the size of the list in the other side putting everything into the session would not be good to your system at all.

Galeixo
  • 102
  • 9
  • I understand that the domain is using lazy loading, but if the Hibernate Session is still open then it should be able to fetch any higher level relationships of the domain. So the question is, why is the hibernate session randomly being closed and why is the domain object becoming detached when the request has not ended? – DeaIss Dec 06 '16 at 12:11