The Texo runtime server environment makes use of JPA/EntityManager to access the underlying database. EntityManager instances are often provided by the container environment in which your code runs. The Texo generated code needs to be able to retrieve an EntityManager instance from the environment in which it runs.
This document explains how Texo works with the EntityManager and it provides pointers on how to integrate your environment with Texo so that one EntityManager/Transaction can be used in the application code, the Texo framework code and as well as in the generated code.
The Texo EntityManager functionality is used by two Texo supported concepts:
The Texo generated code and Texo framework code can get to an EntityManager in different ways:
- the EntityManager member has the @PersistenceContext annotation, so depending on the environment this can work automatically (but you probably need to instantiate your Dao's in a container specific way to make use of this feature).
- an EntityManager can be explicitly set, or
- if no EntityManager is set then the code class will use the EntityManagerProvider.getEntityManager method (described in the next section).
Texo makes use of the EntityManagerProvider which is the central provider of EntityManager instances for Texo (Dao and ObjectStore.
There is a single instance of the EntityManagerProvider available, it can be retrieved using getInstance. You can set your own instance by calling setInstance (both methods are static).
The EntityManagerProvider can be initialized in different ways:
- setting an EntityManagerFactory in the instance, or
- by setting the persistence properties needed to create/initialize an EntityManagerProvider
The EntityManagerProvider supports a special way of creating and managing an EntityManager: getCurrentEntityManager. This method will return an EntityManager which is stored in a ThreadLocal. This corresponds to the getCurrentSession method on a Hibernate SessionFactory.
You can let the EntityManagerProvider work in a 'getCurrentEntityManager' mode by calling setUseCurrentEntityManagerPattern with the parameter true. Then getEntityManager will return the EntityManager stored in the ThreadLocal. This means that subsequent calls in one thread will make use of the same EntityManager. This often make sense.
It is very important to clean/clear up the EntityManager when using the getCurrentEntityManager approach. This because Tomcat (and maybe also other servlet containers) will re-use Threads for different requests. To clean up an EntityManager call EntityManagerProvider.getInstance().clearCurrentEntityManager();
Texo supports the Open-Session-In-View (==Open-EntityManager-In-View) pattern with a specific RequestFilter: org.eclipse.emf.texo.server.store.CurrentEntityManagerRequestFilter
You can set this request filter in web.xml with a filter mapping. In web.xml this would be set like this:
<filter> <filter-name>emFilter</filter-name> <filter-class>org.eclipse.emf.texo.server.store.CurrentEntityManagerRequestFilter</filter-class> </filter> <filter-mapping> <filter-name>emFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
The Texo Open-EntityManager-In-View implementation will:
- try to minimize the load by only performing transaction handling if the application thread actually used an EntityManager.
- still allows you to take control of transaction handling inside the application code, there are no limitations there
- Open-Session-In-View solutions are often also provided by frameworks such as Spring
- Open-Session-In-View has had its share of discussions on the net, see here for some links to those discussions:
The opinion of Texo is that Open-Session-In-View is a great pattern and makes that an application developer does not need to worry about transactions most of the time. Still the implementation should allow a developer to take full control over the transaction handling if needed.