Question

In my grails application in production server I got some issues. In securityFilters I'm injecting springSecurityService and at some point I'm asking something like

if(springSecurityService?.currentUser?.client){
...
}

But system throws an error as

Error 500: Internal Server Error
Class
org.hibernate.LazyInitializationException
Message
could not initialize proxy - no Session
Trace
   Line | Method
->>  32 | doCall            in SecurityFilters$_closure1_closure2_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    82 | doFilterInternal  in com.linkedin.grails.profiler.ProfilerFilter
|   190 | invoke . . . . .  in org.apache.jk.server.JkCoyoteHandler
|   291 | invoke            in org.apache.jk.common.HandlerRequest
|   776 | invoke . . . . .  in org.apache.jk.common.ChannelSocket
|   705 | processConnection in     ''
|   898 | runIt . . . . . . in org.apache.jk.common.ChannelSocket$SocketConnection
^   636 | run               in java.lang.Thread

line 32 is the place where I call if statement mentioned above. Do you have any clue how to solve this LazyInitializationException? What I am doing wrong?

Note : "client" is the domain class which this user belongs to but it is not mentioned in belongsTo parameter of Person

Thanks.

Was it helpful?

Solution 2

To force the domain objects correct work everywhere, you may want to use lazy property. I don't have any idea what your object looks like, but if has any kind of object relations, you may force them to be non-lazy. Just like this:

class Card {
  static hasMany = [cardProperties: CardProperty]
  static mapping = {
    cardProperties lazy: false
  }
}

To ensure you do have some session available, you may want to create a transactional service. Any service would do, but make sure it doesn't contain the line

static transactional = false

If you inject that service to your filters, it will automatically create a transaction and will be able to fetch the lazy properties. But beware! This will begin and finish a transaction. Since you use it in the filter, any page load will have one transaction more.

Another option is to inject the sessionFactory bean to your filter. Then, you may use pure Hibernate syntax. Just like this one:

sessionFactory.getCurrentSession().beginTransaction();

It's not a very good idea, and I would not advise that, but it may work for you. However please note that forwarding the request led to 2 opens of the transaction and 2 closes of the transaction (which is not fine). You'll have to be VERY CAREFUL when deciding whether to commit the transaction. But if you're sure you'll need the database connection on the every page of your app - that may work for you/

OTHER TIPS

The event runs outside of the controller's Hibernate session, so when you load the user it becomes immediately disconnected and lazy-loaded collections or many-to-one references will fail to resolve. The easiest way to fix this is to wrap the user load call in a withTransaction block - it keeps the Hibernate session open the whole time:

AnyDomainClass.withTransaction { status ->
   if (springSecurityService?.currentUser?.client) {
      ...
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top