Spring has wide support for ORM technologies, including Hibernate, TopLink, and JDO. The approach Spring takes in how you use their framework makes coding to these ORM options and swapping between them very easy. Spring 2.0 extended this rich support for ORM technologies to include JPA. Table 16.1 shows the Java classes that developers are interested in for using EJB 3 JPA in Spring.
Table 16.1 Spring classes available for using JPA
We’ll outline the steps for using the EJB 3 JPA from your web applications. We’ll assume you have some basic familiarity with Spring and that you are comfortable with entity packaging and EAOs.
We’ll primarily focus on using jpaDaoSupport and JpaTemplate, because they are intended to simplify the use of the EJB 3 JPA by shielding you from the details of the EntityManager API. We’ll assume you have experience with the general usage of the EntityManager API (which means you’ll appreciate even more how Spring is trying to simplify the EJB 3 JPA programming model).
Suppose that the ActionBazaar developers thought it would be cool to use Spring in their systems. They started creating a prototype to use Spring with JPA, and decided to implement a part of ActionBazaar in Spring as shown in figure 16.1.
We’ll work with the ActionBazaar bidding module shown in figure 16.1, in which a simple Spring EAO (BidSpringEAO) is used for accessing the ActionBazaar persistence unit using Spring’s JpaTemplate. We’ll create a Spring bean (BidService) and configure it to use the EAO. We’ll build an EAO that uses Spring’s JpaTemplate to manipulate entities and use the EAO in a Spring service bean. Finally, we’ll explore the Spring configuration that magically glues the EntityManager, EAO, and the Spring bean together.
Building JPA EAOs for Spring
In topic 12 you learned that the Entity Access Object design pattern improves code maintainability by decoupling the persistence logic from the business logic. Spring provides EAO (Spring still calls it DAO) for JPA and many O/R mapping frameworks such as Hibernate and TopLink.
Spring provides two ways to access and manipulate entities in building Spring EAOs: using the JPA API directly or using JpaTemplate. In topic 12 we used EAOs to call the EntityManager API directly. We’ll now demonstrate how to change the implementation classes to use JPA from Spring applications with the Spring JpaTemplate. Listing 16.1 shows the ActionBazaar EAO implementation classes you need when using JPA from Spring applications. Note that the Spring classnames continue to use the DAO naming convention instead of the revised EAO naming that we’re featuring in this topic.
Figure 16.1 This ActionBazaar bidding module uses Spring with JPA. The Spring bean employs an entity access object to access the entities using JpaTemplate.
Listing 16.1 EAO implementation when using JPA from Spring applications
The class that implements the EAO interface must extend JpaDaoSupport Q. Instead of using the EntityManager API, you use JpaTemplate. In listing 16.1, we’ve used the persist and merge methods Q and d to persist or merge entity instances.
How are exceptions handled with regard to JpaTemplate? We’re glad you asked. You need to be aware that JpaTemplate does not throw any persistence API exceptions. Instead, it throws Spring’s DataAccessException. The primary benefit of this to developers is that by translating exceptions into those provided by the Spring framework, the persistence mechanism is neutral. This means you can swap out persistence mechanisms and your application code won’t have to change to support the new framework’s error handling. This makes it easier to migrate from one persistence toolkit to another, or to support multiple toolkits if you are a tool vendor. Table 16.2 describes some of the important methods in JpaTemplate.
Table 16.2 Important JpaTemplate methods provided by Spring
You can use the JpaTemplate methods to access entities. Spring limits some of the repetitive use of the EJB 3 JPA. For example, if you want to you use a dynamic query to retrieve all Bidders with Gold status, then JpaTemplate will yield the following:
The only problem we see with JpaTemplate is that it does not provide finegrained access to the EntityManager API’s methods.
JPA EAO in your service beans
Spring’s service beans are similar to the EJB 3 session beans that you work with to implement business logic. In our example the BidServiceBean is used to place a
The equivalent code with the EntityManager API will look like this:
bid on an item, and it uses the EAOs to manipulate the entities. You can use the EAOs in your service classes, and the EAOs can be injected into the POJOs with Spring’s setter injection as follows:
If you are new to Spring, you must be wondering, "If all classes are POJOs, then how does the framework know about the EntityManager, and how does it inject instances of EntityManager?" It’s all based on a little Spring configuration magic, which we dive into next.
Configuring Spring to use the JPA
The real power of Spring comes from how it configures services via dependency injection. For our example this means you need to configure the EntityManager-Factory. To coax ActionBazaar to work with Spring, you’ll need the configuration shown in listing 16.2.
Listing 16.2 Spring configuration to use JPA
Even if you’re not familiar with Spring, you can probably figure out what’s going on in this configuration file (actionBazaar-service.xml). The first bean instance, entityManager, injects an instance of the EntityManager by retrieving it from the JNDI namespace when it is referenced from another bean instance. The next bean, bidEAO, asks Spring to automatically wire it to use the previous entity-Manager. The final bean, bidService, requests that Spring inject the bidEAO bean as the implementation for it to use at runtime.
Configuring Spring to use the EntityManager
Because Spring is a lightweight container, it can work either inside a Java EE container or independently. Spring can use a container- or an application-managed EntityManager either inside or outside the container. While you’re using Spring within a Java EE container, it acts as a proxy between the container and the application and injects an EntityManager or EntityManagerFactory when your application needs it. That way, you don’t have to worry about including extra JPA code.
In this topic we primarily focus on Spring as a framework within the Java EE container. This means you have to configure Spring so it can retrieve an EntityManager from the Java EE container and inject an instance of an Entity-Manager whenever you use a JpaTemplate. If you’re using Spring within a Java EE 5 container, you must use either the JndiObjectFactoryBean or Spring 2.0′s new jee:jndi-lookup mechanism to wire an instance of EntityManager (as we did in listing 16.2). If you want the new Spring 2.0 configuration instead of JndiObjectFactoryBean, then use this configuration:
As we discussed earlier, Spring 2.0 acts as a container and supports the container-managed EntityManager with JPA. The Spring container manages the persistence unit. You have to use LocalContainerEntityManagerFactoryBean to wire an entityManagerFactory. The LocalContainerEntityManagerFactoryBean reads the persistence.xml packaged in the application to configure the persistence unit by using the data source supplied. It can also perform load-time weaving to search for annotated entity classes. Here is an example configuration of the container-managed EntityManager:
For more information, refer to the Spring documentation.
If you’re using Spring outside a Java EE container, you can use a LocalEntity-ManagerFactory and your configuration will look like this:
This, of course, demonstrates that JPA can work independently of both a Java EE container and EJB 3.
Wiring entity access objects
The EAOs use JpaTemplate, so we need to wire the EAOs to use JpaTemplate’s methods. The EAOs are wired in the Spring configuration as in listing 16.2. If you recall, the EAOs extend the org.springframework.orm.jpa.support.JpaDao-Support and it has a dependency on EntityManager; therefore, we need to inject an instance of EntityManager. Spring’s autowire-by-type mechanism indicates to the Spring container that it should find a single instance of a Spring bean that matches the property being wired. In this case, the EAO class uses the entityManager property to obtain an instance of EntityManager that we defined earlier in listing 16.2. You must pass EntityManager as a property to the EAO as follows:
At runtime Spring will take care of creating the entityManager and injecting it into the EAO.
If you’re using an application-managed entity manager or using Spring with JPA outside the container, you have to wire the entityManageFactory property instead of an entityManager as follows:
Wiring service beans
Your web applications use service beans to access entities from the presentation tier. You simply wire your service beans (as in listing 16.2) in the Spring configuration file to have them injected. Some steps can be quite mechanical, and are required for every EAO and service bean.
Appropriately configuring Spring for your server allows you to deploy the application using Spring, proving again that you can use JPA outside of a Java EE container.
Let’s now examine how you unite the power of Spring and EJB 3 components (session beans and MDBs).