org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.openmrs.Location.tags, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
at org.openmrs.module.chica.advice.QueryImmunizationForecast.run(QueryImmunizationForecast.java:78)
at java.lang.Thread.run(Thread.java:745)
It seems like the Hibernate session used to retrieve the Encounter is closed and the location attribute is just a proxy. Are you opening a new session in this class ? Nesting sessions in general is not recommended.
This is a thread. As far as I know, I must open a session of some kind in a thread class. This code worked fine in Openmrs 1.7.x but breaks in 1.9.x some I’m not sure what changed with session management. It seems like the session gets closed as soon as the encounter is retrieved.
I don’t know of any specific changes that would have caused this to break, but these days we recommend against the scheduler.username/scheduler.password approach (since it exposes login credentials within the app), but instead you should use this method:
Apparently we have no wiki documentation about this, but the idea is that if your module activator defines a setDaemonToken(DaemonToken) method then it will be called on startup, and you can later use this token to execute code in a daemon thread (which is already authenticated, by the framework)
The encounter passed in the constructor was retrieved in another session and has attributes not loaded (location at least, but can be any), This is bad in general because you shouldn’t assume all the attributes are hydrated. Core services must not load eagerly all the attributes for performance reasons.
I suggest to pass the encounter id to the constructor and load the Encounter object in this session.
@lluismf Thanks. That did the trick. @darius Thank you for the suggestion. It is a little tricky for us to do that since we use Thread pooling and don’t have an easy way to control how the thread is executed. Thank you both for your help.