I've recently run into a situation where I've got a transaction that spans multiple requests and I receive a LazyInitializationException when I attempt to save and commit the changes to the object on the final request. Specifically, I load a TaskInstance in one request, and then (potentially several requests later) I set the actorId on the TaskInstance and save it. The concept is that a user loads a group queue in one request and then "claims" a task by assigning it to himself in another request.
There are a number of ways I can handle this, but I wanted some advice as to which method is preferred. First, I could iterate over the list of tasks as I load them and invoke property accessor methods to force lazy properties to initialized during the same session. I believe this is straightforward and within the intended use of jBPM, but is wasteful if the user never "claims" the task.
Or, I could re-load a fresh copy of the task instance just prior to updating it. This would ensure that the working copy is associated with the current session, but this is equally wasteful as it involves an unnecessary extra query (potentially more, if lazy initialization is involved).
A preferred approach would be to implement the session-per-request with detached objects pattern and simply re-attach the TaskInstance objects to the session prior to accessing lazy properties. Since JbpmContext exposes the Hibernate session this is technically possible, but I am not sure if this is the intended use.
Since jBPM wraps and manages the Hibernate session and transactions, it might make more sense to manage this process inside of JbpmContext. For example, a call to JbpmContext.save(TaskInstance task) would first call session.contains(task) to determine if the task is in the Hibernate session. If not, it would then call session.lock(task, LockMode.NONE) to re-associate the task to the session prior to accessing lazy properties. This would only be necessary for operations that access lazy properties, and could be made more sophisticated by using Hibernate.isInitialized(). (Note: this would not work in every case as there is a potential for a NonUniqueObjectException if an operation is attempted on another instance with the same ID.)
Is using the Hibernate session to re-attach objects in our code appropriate? Has it been tested? Are there potential conflicts with the jBPM code that manages the Hibernate session? Or should I try to initialize everything up front and/or re-load objects prior to modifying them?