Friday, May 11, 2012

Grails org.hibernate.LazyInitializationException: could not initialize proxy - no Session

I was getting this exception which working on a series of domain objects at once. The problem is a well known one, and there are various posted solutions but none of them seemed to apply to me.

Stackoverflow.. They walk about using attach to manually attach to session..
Another Stackoverflow. This time talking about stale DB connections. Not applicable to me, but interesting nonetheless. 
Grails mailing list. Talks about wrapping DB calls in a withTransaction. This could be a runner.. I haven't tried it yet though.

 A quick explanation of my code. The code is calculating reconciliation values. Nothing complicated. The problem sems to be when I look up a currency value in a domain class embedded within the main loop domain object. I have loaded this domain object eagerly, so in theory all the component pieces should also get loaded, but this does not fix the problem.

The commented line  below caused the problems. Explicitly loading each component class seems to fix the problem. This is obviously slow , but speed is not important in this app.

One compounding problem was that this worked on my local environment, but failed in a test environment, so it proved difficult to recreate.

 bank.each(){
        def dcmAccounts = DcmAccount.findAllByDcm(it, [fetch:[fund:"eager", clearingHouse:"eager"]]) // This line fixes the problem
        Long subPercent =percent
        if(dcmAccounts.size()>0){
            subPercent = percent / dcmAccounts.size()
        }
       
        dcmAccounts.eachWithIndex {DcmAccount dcmAccount, cIndex ->
          //def exchangeRate =
ExchangeRate.findByCurrency(dcmAccount.fund.curerncy)?.rate  // This line caused the problem. The fund object is lazily instantiated so when I go to access it, the session has expired. But eagerly loading the funds at the start fixed it
          def a=dcmAccount.fundId
          def b = Fund.get(a).currencyId
          def c = Currency.get(b)
          BigDecimal exchangeRate = ExchangeRate.findByCurrency(c)?.rate
          FundSegregation fundSegregation = new FundSegregation(fundNumber:dcmAccount.fund.fundNumber,fund:dcmAccount.fund, dcmAccount:dcmAccount, limit: dcmAccount.excessCollateralLimit)
          fundSegregation.buildDcmCollateral()
          fundSegregation.buildPledgedCollateral()

No comments: