Section 5.2. Using Spring with JDO

team bbl


5.2. Using Spring with JDO

JDO is the non-EJB standard for persistence in Java applications. In this section, we'll use our favorite JDO implementation, Kodo, to implement transparent persistence for our application. In this section, I'm not going to try to teach you JDO, but I will show you how to use it to provide persistence to our application.

If you've followed JDO for any length of time, it probably brings to mind all sorts of feverish battles with the intensity of the Crusades. Until recently, most people avoided JDO. With the pending release of JDO 2.0 and several solid commercial and open source JDO implementations, this persistence standard seems to be gathering momentum as a stronger player in the ORM space. In fact, my favorite ORM implementation is Solar Metric's Kodo, possibly the leading JDO implementation. It seems to be more robust than the alternatives when it comes to commercial implementations. It's got more flexible mapping support, it's easier to manage, and it's got far richer support for hardcore enterprise persistence. Consider these advantages:

  • You can choose between a variety of open source JDO implementations if you're looking for something that's free, or better control of the source code.

  • You can choose a commercial implementation, and get support and maintenance for a reasonable price if you don't.

  • With the top commercial vendors, you get incredible power and performance, from better management to flexible mapping.

  • You get all of this with the protection and security that an open standard provides.

5.2.1. How do I do that?

You'll use JDO to create a persistent model, and then use that model through a façade layer. The application already has a business domain model created. It's not yet persistent, though. You've also got the interface for the façade layer. You need only do the following steps to enable our application for JDO:

  1. Make the domain model persistent. Do that through the byte code enhancer.

  2. Configure Spring to use Kodo by making a few simple changes in the configuration file.

  3. Build a façade that uses a persistent model through the JDO templates.

That's it. Spring will manage the core JDO resources, consisting of the PersistenceManagerFactory and the PersistenceManager. Think of these special options as the data source and connection for JDO. You can let Spring manage transactions. The three steps above are all that you need.

First, you need to download and install Kodo. Start with the trial version, which you can find at http://www.solarmetric.com. You can use Version 3.2.1 for this book. Once again, you have to add the libraries found in /kodo-jdo-3.2.1/lib to our /lib folder.

To make the model persistent, modify the Ant task to add JDO's byte code enhancement step: add an Ant task to do so, like in Example 5-6.

Example 5-6. build.xml
<taskdef name="jdoc" classname="kodo.ant.JDOEnhancerTask"/> <target name="jdo.enhance">     <jdoc>             <fileset dir="${src.dir}">                    <include name="**/*.jdo" />             </fileset>     </jdoc> </target>

You'll also add path elements to your Ant build file for kodo-jdo.jar, jdo-1.0.1.jar, and jakarta-commons-lang-1.0.1.jar.

Next, build the persistence mapping. The easiest way is through Kodo's wizard. Launch the Workbench (in the \bin directory of your Kodo install) and choose MetaData Create MetaData from the menu. Conversely, you can use the metadatatool and mappingtool scripts that can be found in /kodo-jdo-3.2.1/bin, which are just launchers for kodo.jdbc.meta.MappingTool and kodo.meta.JDOMetaDataTool, respectively.

To keep things consistent with other JDO versions, though, you're going to build a mapping from scratch, with XML. Generate a .jdo file with our class metadata as well as a .mapping file. Both files reside in the /war/WEB-INF/classes/com/springbook folder.

Example 5-7 shows the metadata file.

Example 5-7. package.jdo
<?xml version="1.0" encoding="UTF-8"?> <jdo>    <package name="com.springbook">       <class name="Bike">          <extension vendor-name="kodo" key="detachable" value="true"/>          <field name="reservations">             <collection element-type="Reservation"/>             <extension vendor-name="kodo" key="inverse-owner" value="bike"/>             <extension vendor-name="kodo" key="element-dependent"                 value="true"/>          </field>       </class>       <class name="Customer">          <extension vendor-name="kodo" key="detachable" value="true"/>          <field name="reservations">             <collection element-type="com.springbook.Reservation"/>             <extension vendor-name="kodo" key="inverse-owner"                 value="customer"/>             <extension vendor-name="kodo" key="element-dependent"                 value="true"/>          </field>       </class>       <class name="Reservation">          <extension vendor-name="kodo" key="detachable" value="true"/>       </class>    </package> </jdo>

Example 5-8 shows the mapping file.

Example 5-8. package.mapping
<?xml version="1.0" encoding="UTF-8"?> <mapping>    <package name="com.springbook">       <class name="Bike">          <jdbc-class-map type="base" pk-column="BIKEID" table="BIKES"/>          <field name="bikeId">             <jdbc-field-map type="value" column="BIKEID"/>          </field>          <field name="frame">             <jdbc-field-map type="value" column="FRAME"/>          </field>          <field name="manufacturer">             <jdbc-field-map type="value" column="MANUFACTURER"/>          </field>          <field name="model">             <jdbc-field-map type="value" column="MODEL"/>          </field>          <field name="reservations" default-fetch-group="true">             <jdbc-field-map type="one-many" ref-column.BIKE                 table="RESERVATIONS"/>          </field>          <field name="serialNo">             <jdbc-field-map type="value" column="SERIALNO"/>          </field>          <field name="status">             <jdbc-field-map type="value" column="STATUS"/>          </field>          <field name="weight">             <jdbc-field-map type="value" column="WEIGHT"/>          </field>       </class>       <class name="Customer">          <jdbc-class-map type="base" pk-column="CUSTID"              table="CUSTOMERS"/>          <field name="custId">             <jdbc-field-map type="value" column="CUSTID"/>          </field>          <field name="firstName">             <jdbc-field-map type="value" column="FIRSTNAME"/>          </field>          <field name="lastName">             <jdbc-field-map type="value" column="LASTNAME"/>          </field>          <field name="reservations" default-fetch-group="true">             <jdbc-field-map type="one-many" ref-column.CUST                 table="RESERVATIONS"/>          </field>       </class>       <class name="Reservation">          <jdbc-class-map type="base" pk-column="RESID"              table="RESERVATIONS"/>          <field name="bike">             <jdbc-field-map type="one-one" column.BIKE/>          </field>          <field name="customer">             <jdbc-field-map type="one-one" column.CUST/>          </field>          <field name="reservationDate">             <jdbc-field-map type="value" column="RESDATE"/>          </field>          <field name="reservationId">             <jdbc-field-map type="value" column="RESID"/>          </field>       </class>    </package> </mapping>

It's almost too easy. There's no persistence in the model itself, and that's why you use OR technologies. Still, you'll need a layer of code to use that persistence model for your application. That's the façade layer. You'll see a series of calls to the template. Specify the JDO query language statements for the finders, and the objects to persist for deletes, updates, and inserts. You've already got an interface, but we still need to implement the façade (Example 5-9).

Example 5-9. KodoRentABike.java
public class KodoRentABike extends JdoDaoSupport implements RentABike {     private String storeName;     public List getBikes( ) {         return (List)getJdoTemplate( ).find(Bike.class);     }     public Bike getBike(String serialNo) {         Collection c = getJdoTemplate( ).find(Bike.class,             "serialNo == '" + serialNo + "'");         Bike b = null;         if(c.size( ) > 0) {             b = (Bike)c.iterator( ).next( );         }         return b;     }     public Bike getBike(int bikeId) {         return (Bike)getJdoTemplate( ).            getObjectById(Bike.class, new Long(bikeId));     }     public void saveBike(Bike bike) {         getJdoTemplate( ).makePersistent(bike);     }     public void deleteBike(Bike bike) {         getJdoTemplate( ).deletePersistent(bike);     }     //etc.

Finally, you need to set up some configuration to wire it all together. First, Example 5-10 gives the JDO configuration.

Example 5-10. kodo.properties
# To evaluate or purchase a license key, visit http://www.solarmetric.com kodo.LicenseKey: YOUR_LICENSE_KEY_HERE javax.jdo.PersistenceManagerFactoryClass: kodo.jdbc.runtime.JDBCPersistenceManagerFactory javax.jdo.option.ConnectionDriverName: com.mysql.jdbc.Driver javax.jdo.option.ConnectionUserName: bikestore javax.jdo.option.ConnectionPassword:  javax.jdo.option.ConnectionURL: jdbc:mysql://localhost/bikestore javax.jdo.option.Optimistic: true javax.jdo.option.RetainValues: true javax.jdo.option.NontransactionalRead: true javax.jdo.option.RestoreValues: true kodo.Log: DefaultLevel=WARN, Runtime=INFO, Tool=INFO kodo.PersistenceManagerImpl: DetachOnClose=true

The Spring context will need to wire together the JDO persistence manager, the persistence manager factory, the façade, and any services on the façade. That's done in the context (Example 5-11).


Note: Notice the detachOnClose. This makes sure that JDO loads anything that's lazy before the connection goes away, so that other parts of your application, like the view, can only access beans that have already been loaded.
Example 5-11. RentABikeApp-servlet.xml
<bean  >     <property name="configLocation">            <value>E:\RentABikeApp\war\WEB-INF\kodo.properties</value>     </property> </bean> <bean  >     <property name="persistenceManagerFactory">            <ref local="jdofactory"/>     </property> </bean>          <bean  >     <property name="storeName"><value>Bruce's Bikes</value></property>     <property name="persistenceManagerFactory">            <ref local="jdofactory"/>     </property> </bean>

Recall that you've already got a test case that uses the façade, so you can build it and let it rip.

5.2.2. What just happened?

This is a perfect example of the power of Spring. You've radically changed the implementation of your persistence layer, but you haven't affected the rest of the application at all. Here's how it works.

Spring first uses dependency injection to resolve all of the dependencies. Loading the context configures JDO with the data source that you provided, and then sets the persistence manager factory in the façade JDO implementation. Then, when you call a method on the façade, Spring gets you a persistence manager and uses it to process the query that you supply. You can look at it this way: Spring provides a generic JDO façade method, called the template. You plug in the details, and give control to Spring.

When you're biking or when you're coding, one of the most important metrics is efficiency. How much work can you do with each turn of the pedals, or each line of code? Consider the JDO version of the application. The most compelling thing about the Spring programming model is the efficiency. To see what I mean, think about what you don't see here:

  • You don't have exception management cluttering the lower levels of your application. With Spring's unchecked exceptions, you can get the exception where it's appropriate to do something with it.

  • You don't have resource management. Where JDBC has connections, JDO has the persistence manager. Spring configures the persistence manager factory, and manages the persistence manager within the template for you.

  • You aren't forced to manage transactions and security in the façade. Spring lets you configure these things easily so that you can strip all of the ugly details out of your façade layer and let it concentrate on using the persistent model.

All of this is done for you in the Spring template, in code that comes with the Spring framework, which you can read for better understanding or debug in a pinch. In short, you can get more leverage with each line of code, much like running your bike in a higher gear. That's the bottom line for all of the most successful frameworks and programming languages.

    team bbl



    Spring. A developer's Notebook
    Spring: A Developers Notebook
    ISBN: 0596009100
    EAN: 2147483647
    Year: 2005
    Pages: 90

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net