I have Java EE application with about 10 EntityManagers (number of EMs will probably increase). My application also contains many stateless, statefull and message driven bea
Composite persistence units - Java EE
The way to handle multiple entity managers, i.e. multiple persistence units, in Java EE is to use composite persistence units (CPUs). Such a composite persistence unit can be assessed from one single point in the EE web-application, a datalayer. This needs to be a @Stateless EE bean though in order to work with the @PersistenceContext.
Composite persistence units have been introduced to make possible reusing entity classes, among various Java applications. CPUs are a feature of Enterprise architecture. I choose to use EclipseLink as showcase, as I have positive experience with that from a running production application.
Introduction
In some cases, entities contain general data that is needed across more web-services in a server landscape. Take for example a general ‘name-address’ entity, a ‘user-password-role’ entity, a ‘document-keyword-index’ entity, etc. A composite persistence unit implementation facilitates that the source of each entity definition is specified in only one place (‘single point of definition’). These entity definitions can subsequently be included in each Java web-application that needs this entity access.
Working of composite persistence unit
The working of a composite persistence unit is illustrated by the following tutorial: EclipseLink composite persistence units
The concept of composite persistence units works by first defining member persistence units. Each member persistence unit may be associated with a different database, but the member persistence units can also all refer to the same actual database. I have experience with the latter, where EclipseLink (version 2.6.4) was used in combination with one Postgress database.
Maven is needed to make possible the required modular approach.
Settings in persistence.xml
A composite persistence unit member is defined as follows: Program a group of related entities (Java @Entity classes), one-by-one, in a dedicated Maven module. Define in this Maven module also a composite persistence unit member (important!). The composite unit member PuPersonData refers to this set of related entities that characterizes person data. Define the member persistence unit PuPersonData as (
...
jdbc/PostgresDs
...
).
In a second Maven module, define another composite persistence unit member, PuWebTraffic (
...
jdbc/PostgresDs
...
). Include here other entities (Java classes denoted with @Entity) that store data about web-transactions, logon, sessions, etc.
Needless to state, the two composite persistence unit members must be disjoint with respect to entities, no overlap is allowed in entity-names.
Both persistence unit members have in their XML-definitions the property:
...
Composite persistence unit
We now define in a third Maven module the composite persistence unit CPuPersonSessionData that includes both the persistence units members PuPersonData and PuWebTraffic.
This composite persistence unit CPuPersonSessionData refers to the two persistence unit members, PuPersonData and PuWebTraffic, by means of including the jars that result from compilation of the two pertaining Maven modules.
...
PuPersonData.jar
PuWebTraffic.jar
...
In the XML-definition of the composite persistence unit, the following property needs to be set
...
This setting ensures that the composite persistence unit is treated differently by Java EE than its persistence unit members.
Use of persistence unit in Java
In the Java web-application that is going to store and retrieve entities with both person-data and traffic-data, only the composite persistence unit is included
@Stateless
public class DataLayer {
@PersistenceUnit(unitName="CPuPersonSessionData")
EntityManager em;
...
The normal 'em' operations such as persist, find and merge can now be performed on each entity, contained in one of the composite entity members.
Under Payara, no XA-transactions were needed for this composite persistence unit to address the entities pertaining to each of the persistence unit members.
Maven
The Maven parent POM file needs to contain the specifications for the pertaining modules.
...
PersonData
WebTraffic
PersonSessionData
...
The POM-file of each module needs to be configured as a normal Maven-project, referring to the parent POM-file.
Pitfalls:
The benefit gained is a neat Enterprise data-layer that works with reusable entities, each with one central definition. Moreover, it is possible to perform cross-unit native SQL-queries. I got this to work also.
Documentation states that cross-unit native queries will not work when the composite persistence unit members run on different, actual databases. This should still be verified.