db-jdo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Jdo Wiki] Update of "PersistentInterfaces" by CraigRussell
Date Wed, 31 Aug 2005 22:31:04 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Jdo Wiki" for change notification.

The following page has been changed by CraigRussell:
http://wiki.apache.org/jdo/PersistentInterfaces

New page:
Persistent Interfaces are a feature of JDO 2 that allows users to define their domain object
model in terms of Java interfaces instead of Java classes. For example, this defines a persistence-capable
class called Company with two persistent fields:
{{{
class Company {
  long companyid;
  String name;
}

<class name="Company">
  <field name="companyid" primary-key="true"/>
  <field name="name" column = "NAME"/>
</class>
}}}
To use an interface instead, this defines a persistent interface called ICompany with two
properties.
{{{
interface ICompany {
  long getCompanyid();
  void setCompanyid(long id);
  String getName();
  void setName(String name);
}

<interface name="ICompany">
  <property name="companyid" primary-key="true"/>
  <property name="name" column = "NAME"/>
</interface>
}}}

A goal is to map the interfaces in package org.apache.jdo.tck.pc.company (hereinafter "the
company package") to exactly the same schema as is used for the classes, and to use the same
{{{CompletenessTest}}} and xml data. This way, any bug fixes to the handling of the schema,
xml data, or comparison of data will be propagated to the interface tests.

To change the xml test data to use factories, the attribute {{{factory-method}}} is added
to the test data {{{bean}}} elements.
{{{
    <bean id="company1" class="org.apache.jdo.tck.pc.company.Company">
        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
        <constructor-arg index="1" type="java.lang.String"><value>Sun Microsystems,
Inc.</value></constructor-arg>
        <constructor-arg index="2" type="java.util.Date"><value>11/Apr/1952</value></constructor-arg>
    </bean>
}}}
is changed to become
{{{
    <bean id="company1" class="org.apache.jdo.tck.pc.company.CompanyFactoryImpl"
            factory-method="newCompany">
        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
        <constructor-arg index="1" type="java.lang.String"><value>Sun Microsystems,
Inc.</value></constructor-arg>
        <constructor-arg index="2" type="java.util.Date"><value>11/Apr/1952</value></constructor-arg>
    </bean>
}}}

The package has been refactored to have each domain class implement the corresponding interface.
The algorithm of the CompletenessTest is to create an in-memory domain model graph from xml
data and make its elements persistent. Then, a different in-memory domain model graph is constructed
from the same xml data and the new graph is compared to the persistent graph fetched from
the database.

Since persistent instances that implement the persistent interfaces use a factory pattern,
we introduce a CompanyFactory concept that allows a runtime switch between various factories.
The graph that is compared to the persistent graph is always constructed using the class factory.
The persistent graph is constructed using one of these concepts:

 * the factory instantiates a new instance of the class
 * the factory calls pm.newInstance on the interface
 * the factory calls pm.newInstance on an abstract class that implements the interface

CompanyFactory is the interface that each factory must implement. The methods in the interface
are those that are required by the current xml data implementations. They include constructors
for each concrete class in the model. 

The strategy for implementation is for a concrete class CompanyFactoryImpl that contains a
default implementation that instantiates a new instance of the class. An abstract CompanyFactory
contains skeleton implementations for each required method, and an abstract method to create
a new instance with no properties set. The properties are then set using setProperty methods.

{{{
public abstract class CompanyFactoryInterfaceAbstractImpl implements CompanyFactory {
    
    protected PersistenceManager pm;
    
    /** Creates a new instance of CompanyFactoryPersistentInterface */
    public CompanyFactoryInterfaceAbstractImpl(PersistenceManager pm) {
        this.pm = pm;
    }

    abstract IAddress newAddress(); // implemented in subclass

    public IAddress newAddress(long addrid, String street, String city,
        String state, String zipcode, String country) {
        IAddress result = newAddress();
        result.setAddrid(addrid);
        result.setStreet(street);
        result.setCity(city);
        result.setState(state);
        result.setZipcode(zipcode);
        result.setCountry(country);
        return result;
    }
...}}}

All a concrete factory implementation has to do is to subclass the abstract CompanyFactoryAbstractImpl
and provide implementations for the interfaces.

{{{
public class CompanyFactoryPersistentInterface 
        extends CompanyFactoryInterfaceAbstractImpl {
    
    /** Creates a new instance of CompanyFactoryPersistentInterface */
    public CompanyFactoryPersistentInterface(PersistenceManager pm) {
        super(pm);
    }
    
    IAddress newAddress() {
        return (IAddress)pm.newInstance(IAddress.class);
    }
...
}}}


A new system property {{{jdo.tck.mapping.companyfactory}}} is used to pick the company factory
for the persistent object graph. After constructing the persistent object graph, the default
factory is set so during construction of the compared objects the standard constructor is
used. The maven.xml file needs to pass the system property to the CompletenessTest. 
{{{
  <goal name="doRuntck.jdori">
    <java fork="yes" dir="${jdo.tck.testdir}"
      <sysproperty key="jdo.tck.mapping.companyfactory" 
        value="${jdo.tck.mapping.companyfactory}"/>
    </java>
  </goal>
}}}
Configurations can specify this property in the .conf file:
{{{
cat test/conf/clr.conf
jdo.tck.description = Completeness test with factory class
#jdo.tck.mapping.companyfactory=
#  org.apache.jdo.tck.pc.company.CompanyFactoryImpl$DefaultCompanyFactoryImpl
jdo.tck.mapping.companyfactory=
  org.apache.jdo.tck.pc.company.CompanyFactoryPersistentInterface
jdo.tck.classes = org.apache.jdo.tck.mapping.CompletenessTest
jdo.tck.testdata = org/apache/jdo/tck/pc/company/companyNoRelationships.xml
jdo.tck.mapping = 0
}}}
We also need a factory that uses the persistence manager newInstance method with the persistence-capable
class as the argument.

All the components described so far will remain in the company package. I propose to add the
components to instantiate persistent abstract classes into a subpackage, {{{org.apache.jdo.tck.pc.company.acompany}}}
and to implement the abstract classes that implement the interfaces as well as the company
factory that instantiates the abstract classes using the persistence manager newInstance method
with the abstract class as the argument.

Mime
View raw message