This is an internal documentation. There is a good chance you’re looking for something else. See Disclaimer.
The ContextService is a service that implements the Context interface. This is the implementation that is injected into other services, when they need to access the Context. It is important to properly close a session to avoid memory leaks.
Implicitly and explicitly created contexts¶
There is exactly one implicit context per thread, which is created when the current context is accessed for the first time (typically through the ContextService). Unless the user manually creates additional contexts, all the persistence calls are handled by the implicit context. It is stored in a ThreadLocal variable in the ContextManagerAdapter. The implicit context is automatically closed when the underlying session will be closed by the SessionFactoryManager.
Sometimes it is necessary to create an isolated context for specific work. New contexts can be created by the ContextManager. Unlike the implicit context, all additional contexts must be manually closed by the user.
The ContextManagerAdapter maintains a map which keeps track of all explicitly created contexts. This is necessary to be able to find a specific context instance by the session it references.
This also makes it possible to attach an open context to a new thread. This is not recommended (the session is not thread safe), but required by some legacy code.
Whenever a new context is created, a Hibernate session is opened and passed to this context.
Current session and current context¶
If the current session is requested from the SessionFactory the call is delegated
to an implementation of CurrentSessionContext.
We configure the ManagedSessionContext by
setting the property
hibernate.current_session_context_class (see HibernatePropertiesProvider).
The ManagedSessionContext requires the Session to be set explicitly when the current session is requested, otherwise an exception will be thrown. In contrast, the previously used ThreadLocalSessionContext creates a new session when none was set, but it’s a ‘protected’ session that always requires a transaction and is not compatible with our API. Thus it’s better to just throw an exception when no session was set explicitly (as this should never occur anyway).
The SessionFactoryManager manages the hibernate sessions. All access to hibernate sessions should be made through this class! This central management of sessions makes sure that the old Context based API can be used in combination with the new PersistenceService.
For example, when a new implicit session is created because the PersistenceService API has been accessed,
realizes that the implicit session already exists (even though no implicit Context instance exists yet) and re-uses this session.
This class holds a thread local reference to the ‘implicit’ session. This is the session that is created automatically when the persistence layer is accessed for the first time during a request and no session has been opened explicitly.
If the current session is requested (
getCurrentSession()), the session bound to the ManagedSessionContext is returned.
If nothing is bound, the implicit session is returned (and created if necessary) and bound to the ManagedSessionContext.
It is also possible to explicitly create a new session (using
createNewSession()). Explicitly created sessions
are always bound to the ManagedSessionContext. Explicitly created sessions need to be closed manually!
A BaseSessionEventListener is registered with the session
which detaches the closed session and re-attaches the previous session (if there was one).
A SessionFactoryManagerListener can be registered
with the SessionFactoryManager. It’s
sessionClosing() methods are called for every session that has been created
that are spring components will also be automatically registered.
The current Context is always the context which references the current session.
ContextManagerAdapter#getThreadContext() returns the current context:
The current session is retrieved from the SessionFactoryManager (this might create a new implicit session)
Check if there is an explicitly created context belonging to this sessions and return it (explicitly created contexts are cached in a
Check if the current session is the implicit session. If yes, check if there already is an implicit context instance for this thread and return it. If not, create a new implicit context instance and store it in the ThreadLocal. A BaseSessionEventListener is added to this session, to make sure that the ThreadLocal is cleared when the implicit session is closed.
If none of the above applies, it must be an explicitly opened session –> create a context instance for it
Setting the current context¶
The current session is set (or removed) when
ContextAdapter#resume() is called.
The session of that context is then bound to or detached from the current thread using the
detachSessionFromThread() methods of the SessionFactoryManager.
ContextAdapter#resume() is called by default when a new context is created.
FlushMode.COMMIT so that all changes in the session are flushed to the database just before the transaction is
We currently cannot use
FlushMode.AUTO (which flushes all changes before a query, to make sure the query will return
up-to-date results), because we depend on commit listeners being executed before the changes are flushed to the database.
It’s possible to set a query timeout using
Internally this will set the property
javax.persistence.query.timeout on the underlying