Issue Details (XML | Word | Printable)

Key: JDO-467
Type: New Feature New Feature
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Matthew T. Adams
Reporter: Matthew T. Adams
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
JDO

Named PMF proposal / JDOHelper enhancements

Created: 24/Feb/07 02:11 AM   Updated: 13/Apr/07 10:00 PM
Return to search
Component/s: api2, api2-legacy
Affects Version/s: JDO 2 final
Fix Version/s: JDO 2 maintenance release 1

Time Tracking:
Not Specified

File Attachments:
  Size
Text File Licensed for inclusion in ASF works JDO-467.2007-03-23.patch 2007-03-23 11:39 PM Matthew T. Adams 96 kB
Text File Licensed for inclusion in ASF works JDO-467.2007-03-24.patch 2007-03-24 06:44 PM Matthew T. Adams 116 kB
Text File Licensed for inclusion in ASF works JDO-467.2007-03-29.patch 2007-03-30 04:21 PM Matthew T. Adams 112 kB
Issue Links:
Reference
 
dependent
 

Resolution Date: 06/Apr/07 04:52 PM


 Description  « Hide
From the email on the expert group & jdo-dev alias:

This is a proposal we discussed on the Fri Feb 23 JDO conf call. Please
review and discuss.

Overview:
Currently, there is no way to bootstrap a JDO implementation completely
externally to the source code. The developer is required to provide at
least a resource name that identifies a java.util.Properties file on the
classpath that can configure a single PMF. This makes deployment in
different environments more challenging than necessary.

Motivation:
* Source code is required to be aware of external configuration:
    * In all current JDOHelper.getPersistenceManagerFactory APIs and
    * in order to configure listeners.
* Aligns JDO bootstrapping with JPA bootstrapping concepts.

Proposed Solution:
* Introduce new API methods and JDO equivalent of the JPA persistence
unit concepts, including a jdo.xml file that provides for the
configuration of one or more named PMFs.

Details:
* PersistenceManagerFactory additions

/** Returns the persistence unit name of this PMF. It's the JPA
persistence unit name if configured via persistence.xml or the JDO
persistence unit name if configured via javax.jdo.xml. */
public String getName();

* JDOHelper API additions

/** The default name of the JDO configuration file. */
public static final String DEFAULT_JDO_CONFIG_RESOURCE_NAME =
"javax.jdo.xml";

/** The name of the default persistence unit. */
public static final String DEFAULT_PMF_NAME = "default";

/** Gets the PMF named "default" in the resource "javax.jdo.xml" found
via the current ClassLoader. */
public static PersistenceManagerFactory getPersistenceFactoryManager() {
    return getPersistenceFactoryManagerByName(DEFAULT_PMF_NAME);
}
/** Gets the PMF named pmfName in the resource "javax.jdo.xml" found via
the current ClassLoader. */
public static PersistenceManagerFactory
getPersistenceManagerFactoryByName(String pmfName) {
    return getPersistenceFactoryManagerByName(DEFAULT_PMF_NAME,
DEFAULT_JDO_CONFIG_RESOURCE_NAME);
}
/** Gets the PMF named pmfName in the resource named resourceName found
via the current ClassLoader. */
public static PersistenceManagerFactory
getPersistenceManagerFactoryByName(String pmfName, String resourceName)
{
    return getPersistenceFactoryManagerByName(DEFAULT_PMF_NAME,
DEFAULT_JDO_CONFIG_RESOURCE_NAME, getClass().getClassLoader());
}
/** Gets the PMF named pmfName in the resource named resourceName found
via the current ClassLoader. */
public static PersistenceManagerFactory
getPersistenceManagerFactoryByName(String pmfName, String resourceName,
ClassLoader loader) {
    // reads resource resourceName via given loader
    // configures & returns PMF with the given name
}

* Possibilities for DEFAULT_JDO_CONFIG_RESOURCE_NAME value:
    need to determine file name (similar to persistence.xml)
    javax.jdo.xml
    jdo.xml
    ...

* Proposal for JDO persistence unit configuration XML file
    * Could be more like Spring beans.xml (supporting references, etc.)

    * Note: Square brackets indicate optional elements/attributes

<jdo-config>
    [<extension> elements wherever appropriate]
    
    <!-- Can use attributes for standardized properties -->
    <!-- Can also support vendor-specific attributes and still validate
against schema -->
    <persistence-manager-factory
        [name="default"] <!-- no name implies only the default PMF,
named "default"; can only be one per file -->
        [resource="..."] <!-- convenient for backward compatibility -->
        
        [class="xcalia.ic.jdo.PersistenceManagerFactory"]
        [connection-driver="..."]
        [connection-url="..."]
        [connection-user-name="..."]
        [connection-password="..."]
        [...]
    >
        <!-- or XML-friendly <property> elements -->
        [<property name="javax.jdo...." value="..."/>]
        [<property name="javax.jdo...." value="..."/>]
        [<property name="xcalia.ic...." value="..."/>]
        [...]
        
        <!-- ...and/or properties in java.util.Properties file format?
overrides <property> elements? -->
        <!-- This allows people to continue to use good, old
java.util.Properties format if they want -->
        <properties><![CDATA[
            javax.jdo....=...
            javax.jdo....=...
            xcalia.ic....=...
            ...
        ]]></properties>

        <!-- This provides a way (currently, the only way) to configure
listeners outside of the code -->
        <!-- We'd have to address any class loading issues, since we're
only given a class name -->
        <!-- These should have javax.jdo.listener.... property &
property value equivalents in order to keep old-fashioned
java.util.Property-formatted values consistent with these values -->

        <!-- Method names default to names of corresponding interfaces;
if not present on listener-class, they're a no-op or not even called -->
        [<instance-lifecycle-listener
            listener-class="my.jdo.InstanceListener"
            classes-observed="my.domain.Foo,my.domain.Bar,.."
            [static-factory-method="..."]
            [pre-attach="preAttach"]
            [post-attach="postAttach"]
            [pre-store="preStore"]
            [...]
        />]
        
        <!-- The <instance-lifecycle-listener> element is sufficient,
but we could provide elements for each of the listener types -->
        [<attach-lifecycle-listener
            class="..."
            [factory-method="..."]
            [pre-attach="preAttach"]
            [post-attach="postAttach"]
        />]
        [...]

        <!-- Can optionally include <jdo>, <orm> and <jdoquery> elements
here in order to override annotations, or developer-provided .jdo, .orm,
and/or .jdoquery files (from Erik Bengston) -->
        <!-- Can add attribute to <jdo>, <orm>, and <jdoquery> to allow
for the specifiation of another resource or set of resources on the
classpath (from Craig Russell), for example: -->
        <jdo
resources="META-INF/production-1;META-INF/production-2;..."/>
        
    </persistence-manager-factory>
</jdo-config>


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Matthew T. Adams added a comment - 24/Feb/07 02:14 AM
Here is the XSD as a work in progress, in a pre-alpha state.

Matthew T. Adams added a comment - 02/Mar/07 08:36 PM
Synopsis of discussion on conf call on Fri 2 Mar 07 follows.

NOTE: See questions at the end of this comment!

* PMF already has proposed method getPersistenceUnitName() for 2.1 -- no further changes required
* JDOHelper will have the following changes:
  * Add: public static final String JDO_CONFIG_RESOURCE_NAME = "jdo.xml";
  * Add: public static PersistenceManagerFactory getPersistenceManagerFactory() { return getPersistenceManagerFactory((String)null); }
  * Change: Semantics of methods getPersistenceManagerFactory(String resource) & getPersistenceManagerFactory(String resource, ClassLoader loader) to reflect that if the resource argument is null, then JDOHelper will look for the jdo.xml file and find a persistence-manager-factory element without a persistence-unit-name attribute, and that if the resource argument is non-null, it is taken as a persistence unit name if a jdo.xml is found in the expected location (META-INF) and as a properties file resource name if there is no jdo.xml found.

* Add a default no-op implementation class DefaultInstanceLifecycleListener to javax.jdo.listener so people can extend it and only implement the methods they need to; otherwise, they'll have to implement no-op methods for those that they do not wish to.

* jdo.xml schema
  * Rename to jdoconfig.xsd and root element to jdoconfig to match jdoquery element (no dash).
  * Add documentation
  * Ensure one instance-lifecycle-listener element per implementing class

Questions:

Q: If a jdo.xml is found but there is no persistence-factory-manager element whose name attribute matches the resource, should we throw JDOUserException or fall back to JDO 2.0 & prior behavior, looking for a properties resource by the given resource?

Q: If both a jdo.xml and persistence.xml are found, which has precedence?

Q: The persistence.xml file is required to be in the META-INF/ folder within the persistence archive. What is proposed in JDO 2.1 to align with JPA's concept of a persistence archive?

Matthew T. Adams added a comment - 02/Mar/07 09:36 PM
Proposed answers to question in previous comment.

> Q: The persistence.xml file is required to be in the META-INF/ folder within the persistence archive. What is proposed in JDO 2.1 to align with JPA's concept of a persistence archive?
>
A: There is no longer the notion of "persistence archive" in JPA. Ignored.

> Q: If both a jdo.xml and persistence.xml are found, which has precedence?
>
A: (Note: Multiple jdo.xml files are allowed.) This only matters when there are multiple persistence units (PMF and/or EMF) found with the same names and the user requested a persistence unit of the same name -- if that happens, a JDOUserException should be thrown.

> Q: If a jdo.xml is found but there is no persistence-factory-manager element whose name attribute matches the resource,
> should we throw JDOUserException or fall back to JDO 2.0 & prior behavior, looking for a properties resource by the given resource?
>
A: Fall back to JDO 2.0 behavior.

Matthew T. Adams added a comment - 03/Mar/07 02:01 AM
Here is a patch relative to root/trunk/api20 containing the changes so far. It includes:

* JDOHelper API changes (everything up to the actual jdoconfig.xml parsing)
* Bundle.properties changes
* Addition of jdoconfig.xsd & jdoconfig.dtd

Please review and comment.

Matthew T. Adams added a comment - 03/Mar/07 02:03 AM
For convenience, here is what should be an RC version of jdoconfig.xsd.

Matthew T. Adams added a comment - 08/Mar/07 06:32 PM
This proposal allows external configuration of instance lifecycle listeners; the external configuration of these is currently not specified in JDO 2.1. The implementation direction for JDOHelper to support JDO persistence units (not JPA) is to read the jdoconfig.xml and create a Map instance and then call JDOHelper.getPersistenceManagerFactory(Map properties).

In order to support externally configured instance lifecycle listeners, I propose that we allow new properties in 2.1 of the form

javax.jdo.option.InstanceLifecycleListener.LISTENER_CLASS_NAME=PERSISTENT_CLASS_NAMES

where LISTENER_CLASS_NAME is the fully qualified class name of the user's class implementing InstanceLifecycleListener and PERSISTENT_CLASS_NAMES is the list of PC classes that the listener will observe. If empty or not present, all PC classes are observed.

Example in .properties file format:

javax.jdo.option.InstanceLifecycleListener.com.acme.bleck.blah.MyListener=com.acme.domain.Foo,com.acme.domain.Bar
javax.jdo.option.InstanceLifecycleListener.com.acme.bleck.blah.MyOtherListener

These are the equivalent of

pmf.addLifecycleListener(
    new com.acme.bleck.blah.MyListener(),
    new Class[] {com.acme.domain.Foo.class,com.acme.domain.Bar.class});

pmf.addLifecycleListener(
    new com.acme.bleck.blah.MyOtherListener(), null);

The spec would need to be updated to reflect the prefix "javax.jdo.option.InstanceLifecycleListener." and its use, and JDOHelper would need to be updated with the psf String "javax.jdo.option.InstanceLifecycleListener".

Michelle Caisse added a comment - 09/Mar/07 01:07 AM
Just a comment on style -- imports should be fully qualified, e.g. import java.util.Vector and not java.util.*

See the Coding Standards link at http://db.apache.org/jdo/index.html.

Craig Russell added a comment - 11/Mar/07 04:35 AM
Matthew,

Good start. Here's a partial review of your patches.

1. We don't like to have imports of package.* because it hides the classes/interfaces that are actually used. So your change of the various import java.util. classes to import java.util.* needs to be reverted.

2. Please split the long line containing JDO_CONFIG_RESOURCE_NAME into two < 80 char lines.

3. In general, please use < 80 char lines.

4. I think the javadoc describing the name parameter needs to discuss the jdoconfig.xml and the persistence.xml for configuration.

5. This comment
+ * If name is null, return the unnamed {@link PersistenceManagerFactory}; m
ultiple persistence units with the given
+ * name are found (including null), throw JDOFatalUserException.

could use a bit of editing.

6. Any reason to use "findNamed..." instead of "getNamed..."?

7. Eschew "Remember", as in
Remember, if name == null or name == "", then

8. Stopped at line 211 of the diff, around + /* JDO 2.1:
+ Attempt to find & return named persistence unit here.
+ Remember, if name == null or name == "", then we're looking for the def
ault PMF.

Matthew T. Adams added a comment - 15/Mar/07 06:35 AM
Latest version of patch (relative to trunk/api20), ready for review. Positive test cases all work ok; negative test cases still need to be authored, and code to handle reflection-based use of javax.persistence.Persistence is not yet tested.

Matthew T. Adams added a comment - 23/Mar/07 11:39 PM
This patch includes the changes discussed on the conference call today:
* JDO 2.0 legacy behavior is attempted first in JDOHelper.getPersistenceManagerFactory(String, ...), then new 2.1 behavior is attempted.
* All constants moved into javax.jdo.Constants; PMF no longer extends Constants, only JDOHelper
* All JDO XML resource (DTD, schema) names are present & documented.

Matthew T. Adams added a comment - 24/Mar/07 06:44 PM
Slight refactoring:
* renamed methods "getNamedPersistenceManagerFactory*" to "getPersistenceUnit*"
* refactored tests so that they look for META-INF/jdoconfig.xml in test-specific subdirectories using new test class javax.jdo.ClasspathHelper
* added a few negative tests

This patch supercedes patch JDO-467.2007-03-23.patch.

Matthew T. Adams added a comment - 30/Mar/07 04:21 PM
This patch supercedes any previous ones. Please review.

Matthew T. Adams added a comment - 02/Apr/07 03:06 PM
Committing changes. Still need to fix issues regarding
* use of namespace-aware JAXP APIs (see comment in JDOHelper.java "// TODO: prefer using namespace-aware APIs")
* portable configuration of JAXP DocumentBuilderFactory (see comment in JDOHelper.java "// TODO: ensure DBF is initialized properly")