Using the Java Persistence API with Spring 2.0
by Seth White
03/20/2006
To recap, we have seen how a Spring DAO is injected with a Kodo EntityManagerFactory
, which the DAO uses for all of its persistence work. The Kodo EntityManagerFactory
in turn connects to the Kodo resource adapter through JNDI. We will look at configuring the Kodo resource adapter next, but first there is an additional bit of Spring configuration to be aware of that will help tie everything together.
Spring needs to be told to use the WebLogic JTA transaction manager to begin and commit transactions. This is done in this XML stanza:
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
<property name="transactionManagerName"
value="javax.transaction.TransactionManager"/>
</bean>
The important thing to understand here is that Spring is being told specifically to delegate transactional work to the WebLogic JTA implementation. Later, we will see that Kodo is also told to use JTA transactions in its configuration. This sets things up so that the MedRec service objects will begin a WebLogic JTA transaction and then invoke DAOs in the context of that transaction. The DAOs then invoke Kodo, which performs its database reads and writes as part of the existing WebLogic JTA transaction.
Kodo configuration
We used Kodo 4.0 EA4, which is an early access release of Kodo's JPA implementation. At the time of this writing the EJB 3.0 specifications, which define JPA, are not yet final, so Kodo supports a pre-final version of JPA. Kodo is deployed as a resource adapter into WebLogic Server. The resource adapter is registered in JNDI. Configuration of the resource adapter is done in the standard ra.xml
descriptor file, which is located in the META-INF directory of the resource adapter RAR file.
If you look at the ra.xml
file you will see that Kodo supports a large number of configuration options (a sign of a mature product). However, the sample application only required that we modify a small number of these. Let's take a look at the properties that the sample application required:
<config-property>
<config-property-name>ConnectionFactory2Name</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>jdbc/MedRecGlobalDataSource
</config-property-value>
</config-property>
<config-property>
<config-property-name>ConnectionFactoryName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>jdbc/MedRecGlobalDataSourceXA
</config-property-value>
</config-property>
<config-property>
<config-property-name>TransactionMode</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>managed</config-property-value>
</config-property>
<config-property>
<config-property-name>LicenseKey</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>XXXXXXXXXXXXXXXXXXXX</config-property-value>
</config-property>
<config-property>
<config-property-name>PersistentClasses</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>
com.bea.medrec.domain.Patient,com.bea.medrec.domain.Address,
com.bea.medrec.domain.User,com.bea.medrec.domain.Physician,
com.bea.medrec.domain.Prescription,com.bea.medrec.domain.Record,
com.bea.medrec.domain.Group,com.bea.medrec.domain.VitalSigns
</config-property-value>
</config-property>
One thing that Kodo needs to be told about is the JNDI location of JDBC data sources so that it can interact with the database. In fact, Kodo needs to know about two data sources: one data source for handling transactional work, and another for non-transactional work because Kodo sometimes accesses the database to do work that should not be part of a global transaction. As you may have guessed, the ConnectionFactoryName and ConnectionFactory2Name properties are used for this purpose. The value of each property is the JNDI name of a WebLogic data source. Make sure that ConnectionFactory2Name refers to a data source that does not enroll its connections in global JTA transactions.
Kodo also needs to know if the application is using JTA managed transactions or local transactions. Since MedRec's service beans, which control transactions, are configured to use JTA, we set the value of the TransactionMode property to managed. In addition, you also need to configure the Kodo license in the resource adapter file and list the persistent classes that your application will be using. The properties used for this should be self-explanatory.
If you've had a chance to look at the JPA specification you may have heard about the persistence.xml
file. This is a standard configuration file that contains metadata related to JPA persistence. Kodo supports a persistence.xml
file as well. However, when using the current early access version of Kodo in an application server environment, the persistence.xml
file really just contains a subset of the information specified in the resource adapter configuration and is only used by tools, such as the Kodo enhancer.
Download
The following download includes all Java and other source files for the version of MedRec discussed in this article, as well as the Spring 2.0 and Kodo binaries and their dependencies: medrec-spring-jpa.zip. You will need approximately 27 MB of disk space for the download.
Conclusion
This article has taken a close look at the use of the new JPA support in Spring 2.0, which has been used to reimplement the data access layer of the MedRec sample application. Hopefully, this has given you what you need to begin using these new APIs. If you would like to dig deeper, we encourage you to look at the actual MedRec code included with this article. The sample application code illustrates how to use WebLogic 9.1, Spring 2.0, and Kodo JPA together in an integrated way.
We have seen that the new JPA APIs are both easy to use, intuitive, and at the same time flexible. Java annotations make a huge difference in reducing the amount of metadata required to specify the database mapping. Although JPA is new, it is powerful enough to allow our domain model classes to continue to be used throughout the application in the persistence tier, the Web tier, and the Web services tier. This reuse enables a dramatic simplification in the application architecture and significantly reduces the number of Java classes that a developer needs to write.
Spring 2.0, for its part, provides an elegant facility for creating data access objects that leverage JPA. Spring's data access architecture, making it easy to switch between different persistence technologies without the need to rewrite the rest of the application code.
Additional Reading
- The Spring Framework - Spring Framework official site
- SolarMetric Kodo - Kodo official site
- JSR 220 - Enterprise JavaBeans 3.0, the JSR that defines JPA
Seth White is one of the senior engineers on the WebLogic Event Server team.