EJB 3: From legacy technology to secret weapon

Four factors that streamline and modernize EJB 3 development

1 2 3 4 5 6 Page 4
Page 4 of 6

Persistence implementation

For persistence, you need a JPA deployment descriptor named persistence.xml. Injecting the EntityManager without specifying the persistence unit works only if a single persistence unit is specified in persistence.xml, as in Listing 10.

Listing 10. Injection of EntityManager from the (one and only) default persistence unit

@Stateless
public class BookServiceBean implements BookService {

/*no additional information ...works only for one persistence unit in the persistence.xml*/
@PersistenceContext
private EntityManager em;

public void create(Book book) {
this.em.persist(book);
}
}

In all other cases the reference to the EntityManager must be resolved, either with an attribute of the annotation or in the deployment descriptor. It is a common case to have more than one persistence unit with different configurations. Every injected EntityManager is related to a persistence unit and is independent of the others. Different EntityManagers:

  • Have distinct caches
  • Can be configured differently in persistence.xml
  • Can be used for the realization of different use cases categories

An EntityManager responsible for access to the master data could use aggressive caching, while the EntityManager for the operational data could be configured with a. "weak" reference cache. The one responsible for export/import could be deployed with no cache activated at all.

JPA can be used outside the container as well. This feature is especially useful for testing purposes. However, it requires another persistence unit with dedicated a JDBC driver configuration and RESOURCE_LOCAL transaction handling -- another example of several persistence units inside a persistence.xml deployment descriptor. In the example in Listing 11, both persistence units are identical, except for the database schema generation. The DaC persistence unit drops and creates all tables on deploy and undeploy, respectively. The None persistence unit just relies on the existence of the schema.

Listing 11. Configuration of different persistence units

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
   <persistence-unit name="DaC" transaction-type="JTA">
      <provider>oracle.toplink.essentials.PersistenceProvider</provider>
         <jta-data-source>jdbc/sample</jta-data-source>
            <properties>
               <property name="toplink.ddl-generation" value="drop-and-create-tables"/>
            </properties>
   </persistence-unit>

   <persistence-unit name="None" transaction-type="JTA">
      <provider>oracle.toplink.essentials.PersistenceProvider</provider>
         <jta-data-source>jdbc/sample</jta-data-source>
            <properties>
            </properties>
   </persistence-unit>
</persistence>

Analogous to EJB injection, injection of the EntityManager must be explicitly configured if it is arbitrary and can't be inferred from the convention. The most flexible -- but also most tedious -- way to resolve the dependency is in the deployment descriptor, as in Listing 12.

Listing 12. Resolving the ambiguity in XML

<ejb-jar ...>
   <enterprise-beans>
      <session>
         <ejb-name>BookServiceXMLBean</ejb-name>
            <persistence-context-ref>
               <persistence-context-ref-name>...di.persistence.BookServiceXMLBean/em</persistence-context-ref-name>
               <persistence-unit-name>DaC</persistence-unit-name>
            </persistence-context-ref>
      </session>
   </enterprise-beans>
</ejb-jar>

You can maintain the relation between the injected EntityManager and its persistence unit without recompiling the session bean, which is especially useful for local tests. On the other hand, the deployment descriptor is an additional artifact that you must create and maintain, so this approach is not free. Refactoring, especially, can be challenging, because the IDE must keep the source and XML configuration consistent.

For static resolution, annotations are more appropriate and efficient. You can easily set the persistence unit's name in the @PersistenceContext annotation, as in Listing 13. No additional deployment descriptors are required for this purpose.

Listing 13. Specifying the unit name with annotations.

@Stateless
public class BookServiceAnnotationBean implements BookService {

@PersistenceContext(unitName="DaC")
private EntityManager em;

public void create(Book book) {
this.em.persist(book);
}
}
1 2 3 4 5 6 Page 4
Page 4 of 6