JPOX - Longplay Web Sample application

Longplay is a virtual company that sells video and music products. Longplay does not have a web store seller site, but a list of the commercialized products on web.

Architecture

The Longplay web site runs inside a servlet container and depends on JDO for persistence services. The Longplay web site uses a database connection pool to improve use of resources.



Domain model

The Longplay web site development process is centered and driven by the domain model. The domain model is composed of three classes: Product, DVD and CD. These three classes are persistent and its instances are going to be store in the database.



Database model

You've already heard the saying: "Behind every great man is a great woman", but maybe you've not heard yet the analogous version to applications and databases: "Behind every great application is a great database model". Data is the sustaining factor in typical business applications and put some effort in the database model is far than important to allow consistent storage and efficient access to data.

You can start your database model from scratch or from an existing schema, JPOX support both modes. Therefore creating a new schema or using an existing one will have the same effect in the end. It's important to note that you will have to make the correspondences in a JDO file to match the models.



Domain and Database model matching

The domain and database models do not have to follow one java class to one database table, and you are allowed to normalize or denormalize both domain models and database models.

To make this happen transparently, you have to map the domain model to the database model or vice versa. In JDO, you create JDO metadata files for this purpose.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd">
<jdo>
    <package name="org.jpox.samples.web.model">
        <class name="Product" table="LongplayProduct">
            <!-- a primary-key in the table that does not have a correspondent field -->
            <datastore-identity strategy="identity" column="Product_ID"/>

            <field name="code">
                <column name="code" jdbc-type="VARCHAR" length="50"/>
            </field>
            <field name="description">
                <column name="description" jdbc-type="VARCHAR" length="255"/>
            </field>
            <field name="price"/>
                <column name="price"/> <!-- let DN select the best sql type -->
            </field>
        </class>
        <class name="DVD" persistence-capable-superclass="org.jpox.samples.web.model.Product" table="LongplayDVD">
            <inheritance>
                <join>
                    <column name="Product_ID"/>
                </join>
            </inheritance>
            <field name="starring">
                <column name="description" jdbc-type="VARCHAR" length="255"/>
            </field>
        </class>
        <class name="CD" persistence-capable-superclass="org.jpox.samples.web.model.Product" table="LongplayCD">
            <inheritance>
                <join>
                    <column name="Product_ID"/>
                </join>
            </inheritance>
            <field name="singer">
                <column name="description" jdbc-type="VARCHAR" length="255"/>
            </field>
        </class>
    </package>
</jdo>

The previous snippet shows the JDO metadata for our sample, with the domain model mapped to our database model and several fine tunings (jdbc-type, length, colum and table names). We will let JPOX create the schema for us in the database.

Pitch on the proper solution

To adjust for maximum performance and development experience, we select a set of features to apply in our application:

  • Schema created by JPOX

    Configured at the PersistenceManagerFactory creation by a property, org.jpox.autoCreateSchema , defined in the jdo.properties file. For further reference, see the PMF Guide.

  • Using a DataSource available inside an Application Server or Web Server

    Configured at the PersistenceManagerFactory creation by a property, javax.jdo.option.ConnectionFactoryName , defined in the jdo.properties file.

    javax.jdo.option.ConnectionFactoryName=jdbc/ds
    
    For further reference, see Connection pooling.

  • Custom table and column naming

    User customized table and column names are used in this example.

    
    <?xml version="1.0"?>
    <!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd">
    <jdo>
        <package name="org.jpox.samples.web.model">
            <class name="Product" table="LongplayProduct">
                <field name="description">
                    <column name="description" jdbc-type="VARCHAR" length="255"/>   
                </field>
            </class>
        </package>
    </jdo>
    
    
    For further reference, see Meta-data.

Implementing the use cases

The JDO stuff is done. We are ready to implement the use cases. Our application is very simple, and all we have to do is implement a use case to list the Longplay's products.



To implement the View list of products Use Case, we use a simple Model-View-Controller pattern. The sequence of actions described by the Use Case is implemented by the Controller and the observable value to Actors are presented in Views, in our use case we have only one View.









The above diagram display the objects in collaboration to realize our Use Case. Our use case implementation is just a few lines of code. It gets a PersistenceManager instance, opens a transaction, fetch the contents from the database and make the results transient to be used outside a PersistenceManager context.


    /**
     * Returns a collection of Products
     * @return A collection of Product
     */
    public Collection getProducts()
    {
        PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
        try
        {
            pm.currentTransaction().begin();
            Collection c = (Collection) pm.newQuery(pm.getExtent(Product.class,true)).execute();
            pm.retrieveAll(c);
            pm.makeTransientAll(c);
            Collection products = new ArrayList(c);
            pm.currentTransaction().commit();
            return products;
        }
        finally
        {
            if (pm.currentTransaction().isActive())
            {
                pm.currentTransaction().rollback();
            }
            pm.close();
        }
    }                

Running

The Longplay application is organized with the following structure:

  • src/java : source files
  • src/webapp : html, jsp, gif and jpg files
  • src/webapp/WEB-INF : compiled classes, jdo files and the web.xml file
  • lib : The placeholder for jar files. Don't forget to put the jar files required by JPOX to run
  • build.xml : Ant script for building using Ant
  • project.xml, project.properties, maven.xml : Maven build files.
  • jpox.properties : File defining the data source location and PMF controls

You can build the LongPlay application using either Maven or Ant, and it is available to download from SourceForge.

Summary

This tutorial presented the overall steps required to develop a web application using JDO. We hope that you are now ready to develop web applications using JPOX.