Why the LazyInitializationException
shows up in this workflow
context.commitTransaction()
closes the Hibernate session for this step.
When the step ends, the workflow engine expects the session that it opened at the beginning of the step to still be alive so it can flush and commit after the step finishes. CallingcommitTransaction()
yourself closes that session early and detaches every object that was loaded in it (Identity
, itsLink
s, theApplication
proxies inside each link, etc.).call:refreshIdentity
immediately runs in the very next step.
refreshIdentity
reloads the identity, then walks through the links (link.getApplication()
), roles, entitlements, … If any of those objects are still the detached proxies that were created in the previous (now‑closed) session, Hibernate tries to initialise them and throws
org.hibernate.LazyInitializationException:
could not initialize proxy – no Session
This is exactly the pattern described in SailPoint’s developer thread on this error - org.hibernate.LazyInitializationException.
3. The proxy you see in the stack trace belongs to your AD application (Id 0ad200e18a19…
), so the first lazy fetch that fails is link.getApplication()
.
The fix: let the workflow engine do the commit for you
<Step icon="Task" name="Set Identity Attribute">
<Arg name="identityName" value="ref:identityName"/>
<Script>
<Source><![CDATA[
import sailpoint.object.Identity;
Identity identity =
context.getObjectByName(Identity.class, identityName);
// clear the attributes – use nulls if you really want them removed
identity.setAttribute("iiqleaverdate", null);
identity.setAttribute("termDate", null);
identity.setAttribute("new_uname", null);
identity.setAttribute("comments", null);
context.saveObject(identity); // **no commitTransaction()**
// If you want to be 100 % sure the row is written before
// the next step starts you can add
// sailpoint.tools.Util.flushContext(context);
]]></Source>
</Script>
<Transition to="Refresh Identity"/>
</Step>
- Remove
context.commitTransaction()
– the workflow engine will automatically flush and commit the step when it finishes (see the Business‑Process/Step Action docs) - Determining options when running an identity refresh in a workflow step - Compass. - Because you did not close the session, all proxies belong to a live session and
refreshIdentity
can traverse them safely.
Tip: If, for some reason, you absolutely must commit in the middle of the step, call
context.commitTransaction();
context.startTransaction(); // reopen a fresh session
and *do not* keep references to objects loaded in the old session. Reload them instead.
Best‑practice reminders
Topic | Recommendation |
---|---|
Attribute clearing | Use null (or identity.removeAttribute() ) rather than empty string if you really want the attribute to disappear. |
Locking | When a workflow writes an Identity , use ObjectUtil.lockIdentity() if concurrent updates are possible. |
Performance | Excessive manual commitTransaction() calls can hurt overall throughput. Avoid them inside loops or high‑volume workflows. |
Debugging | If you still see lazy‑load errors, add log4j.logger.org.hibernate=debug to capture the exact field that fails, or reload the object in the current session (context.getObjectById(...) ). |
After removing the premature commit most teams find the refresh step runs without the “no Session” error. Let me know if you still see stack traces – we can look at log excerpts and tune the refresh arguments next.
Cheers!!!