DekGenius.com
[ Team LiB ] Previous Section Next Section

7.1 Configuring a PersistenceManagerFactory

A PersistenceManagerFactory has a number of properties you can use to configure a PersistenceManager. You should initialize these property values when the PersistenceManagerFactory is first created via the JDOHelper interface. Once you have constructed a PersistenceManagerFactory with the necessary property values, you call getPersistenceManager( ) to construct a PersistenceManager instance. The values of the properties in the PersistenceManagerFactory instance become the default settings for the properties in all the PersistenceManager instances created by the factory.

To create a PersistenceManagerFactory, initialize a Properties instance and pass it as a parameter to one of the following JDOHelper methods:

public static PersistenceManagerFactory
                    getPersistenceManagerFactory(Properties props, ClassLoader cl);
public static PersistenceManagerFactory
                    getPersistenceManagerFactory(Properties props);

The second method, without a ClassLoader parameter, uses the ClassLoader in the calling thread's current context to resolve the class name.

Table 7-1 lists the keys that you can specify in the Properties object to initialize the PersistenceManagerFactory. A JDO implementation may have some of its own additional properties that are necessary. Such vendor-specific properties should not have the javax.jdo.option prefix; instead, they should use a prefix that identifies the specific implementation.

Table 7-1. Standard property keys used to initialize a PersistenceManagerFactory
javax.jdo.PersistenceManagerFactoryClass
javax.jdo.option.ConnectionUserName
javax.jdo.option.ConnectionPassword
javax.jdo.option.ConnectionURL
javax.jdo.option.ConnectionDriverName
javax.jdo.option.ConnectionFactoryName
javax.jdo.option.ConnectionFactory2Name
javax.jdo.option.IgnoreCache
javax.jdo.option.Optimistic
javax.jdo.option.NontransactionalRead
javax.jdo.option.NontransactionalWrite
javax.jdo.option.Multithreaded
javax.jdo.option.RetainValues
javax.jdo.option.RestoreValues

The keys and values in a Properties instance are represented by String instances. Each property listed in Table 7-1 has a corresponding property value in PersistenceManagerFactory that is either a String or a boolean. The value of a String property is used directly, without change. In the case of a boolean property, the String value in the Properties instance is considered true if it compares equal to "true" (ignoring case); otherwise, it is initialized to false.

You must include the javax.jdo.PersistenceManagerFactoryClass property, which is used to specify the implementation-specific class of the instance this method returns. The name associated with this property should be the fully qualified name of the implementation's class that implements the PersistenceManagerFactory interface. Your implementation's documentation should provide you with the name of this class.

If you do not initialize a property, the implementation can choose the default value. A JDO vendor will likely choose default values that work best with its implementation. Therefore, the default values are not likely to be consistent across different implementations. To ensure that your application is portable and has consistent behavior across implementations, you should initialize the values of all the properties that are relevant to your application.

The following code populates a Properties instance with JDO properties and constructs a PersistenceManagerFactory using JDOHelper. The RestoreValues property is initialized to false, because its property value is not equal to "true" (ignoring case).

import java.util.Properties;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

...

PersistenceManagerFactory pmf = null;
Properties properties = new Properties(  );
properties.put("javax.jdo.PersistenceManagerFactoryClass",
               "com.sun.jdori.fostore.FOStorePMF");
properties.put("javax.jdo.option.ConnectionURL", "fostore:database/fostore");
properties.put("javax.jdo.option.ConnectionUserName", "dave");
properties.put("javax.jdo.option.ConnectionPassword", "jdo4me");
properties.put("javax.jdo.option.Optimistic", "false");
properties.put("javax.jdo.option.IgnoreCache", "false");
properties.put("javax.jdo.option.RetainValues", "true");
properties.put("javax.jdo.option.RestoreValues", "yes"); // will be set to false
pmf = JDOHelper.getPersistenceManagerFactory(properties);

The two getPersistenceManagerFactory( ) methods delegate to a static getPersistenceManagerFactory( ) method, which should exist in the class named in the javax.jdo.PersistenceManagerFactoryClass property. If any exceptions are thrown while trying to call this static method, a JDOFatalUserException or JDOFatalInternalException is thrown, depending on whether the exception is due to your application or the implementation. The nested exception indicates the cause of the exception. A JDOFatalUserException is thrown if the class specified by the javax.jdo.PersistenceManagerFactoryClass property is not found or accessible. If the class exists, but it does not have a public static implementation of getPersistenceManagerFactory(Properties), a JDOFatalInternalException is thrown. If the method does exist, but it throws an exception, it is rethrown by the JDOHelper method.

Implementations may manage a map of instantiated PersistenceManagerFactory instances that have specific property key values, and return a previously instantiated PersistenceManagerFactory instance with the property values you request. The same PersistenceManagerFactory instance can be returned when the application makes multiple calls to construct an instance with the same property values, using the same or different Properties instances.

The PersistenceManagerFactory interface provides methods to get and set the values of its properties. However, since getPersistenceManagerFactory( ) can return a previously constructed PersistenceManagerFactory instance, the returned instance is sealed (i.e., its properties cannot be changed), and any call to alter a property with a set method throws an exception. Portable applications should therefore completely initialize the PersistenceManagerFactory with the properties in a Properties instance. If you want to call the set methods to initialize property values, you can construct the PersistenceManagerFactory with a vendor-specific constructor. This will return a nonsealed instance that can have its properties changed, but using such vendor-specific constructors is not portable.

7.1.1 Connection Properties

The following connection properties are used to configure a datastore connection:

javax.jdo.option.ConnectionURL

The ConnectionURL property identifies the specific datastore to access. The syntax and value of this parameter is determined by the underlying datastore. If you are using a JDO implementation that is layered on top of a JDBC connection, you will likely specify the same value a JDBC application would use to establish a connection. The JDO implementation uses the ConnectionURL property value to establish its internal JDBC connection.

javax.jdo.option.ConnectionDriverName

The ConnectionDriverName property is used to specify the particular database driver. For example, oracle.jdbc.driver.OracleDriver is a common driver used with Oracle. A ConnectionDriverName is normally required when accessing a relational database with JDBC. Some datastores, such as an object database, do not have multiple drivers. For these datastores, it is not necessary to provide a value for ConnectionDriverName.

javax.jdo.option.ConnectionUserName and javax.jdo.option.ConnectionPassword

Most datastores perform access authentication by requiring a username and password. The ConnectionUserName and ConnectionPassword properties are used to initialize these connection properties. An alternative to providing these two values in the Properties object used to initialize the PersistenceManagerFactory is to call the getPersistenceManager( ) method that accepts the userid and password as parameters.

javax.jdo.option.ConnectionFactoryName

The ConnectionFactoryName property identifies the name of the connection factory from which the JDO implementation should obtain datastore connections. JNDI is used to locate the connection factory with the given name.

Instead of providing the name of the factory, you can directly provide the ConnectionFactory instance by passing it as a parameter to setConnectionFactory( ).

If you are running in a managed environment that has other connection properties that you can and want to set in your application, you can configure a connection factory. When you use a connection factory, the ConnectionURL, ConnectionUserName, and ConnectionPassword connection properties are overridden by the ConnectionFactory and ConnectionFactoryName properties.

If you set multiple connection properties, they are evaluated in order. If you specify ConnectionFactory, all other connection properties are ignored. If you do not specify ConnectionFactory, but you specify ConnectionFactoryName, all other properties are ignored.

If you use a connection factory, you should provide values for the following properties, if the datastore has a corresponding concept:

URL

The URL of the datastore

UserName

The name of the user establishing the connection

Password

The password for the user

DriverName

The driver name for the connection

ServerName

The name of the server for the datastore

PortNumber

The port number for establishing a connection to the datastore

MaxPool

The maximum number of connections in the connection pool

MinPool

The minimum number of connections in the connection pool

MsWait

The number of milliseconds to wait for an available connection from the connection pool before throwing a JDODataStoreException

LogWriter

The PrintWriter to which messages should be sent

LoginTimeout

The number of seconds to wait for a new connection to be established to the datastore

The PersistenceManagerFactory instance may also support additional properties that are specific to the datastore or PersistenceManager.

In an application-server environment, a connection factory always returns connections that are enlisted in the thread's current transaction context. Using optimistic transactions requires an additional connection factory that returns connections that are not enlisted in the current transaction context. (Chapter 15 discusses this in detail.) For this purpose, the ConnectionFactory2Name property and setConnectionFactory2( ) method are used:

javax.jdo.option.ConnectionFactory2Name

The ConnectionFactory2Name property identifies the name of the connection factory from which nontransactional datastore connections are obtained. JNDI is used to locate the connection factory by name.

Alternatively, you can specify the connection factory instance directly by passing it as a parameter to setConnectionFactory2( ).

The following list provides the get and set methods for each of the connection properties:

javax.jdo.option.ConnectionURL

Get method: String getConnectionURL()

Set method: void setConnectionURL(String)

javax.jdo.option.ConnectionUserName

Get method: String getConnectionUserName()

Set method: void setConnectionUserName(String)

javax.jdo.option.ConnectionPassword

Get method: none

Set method: void setConnectionPassword(String)

javax.jdo.option.ConnectionFactoryName

Get methods: String getConnectionFactoryName( ), Object getConnectionFactory( )

Set methods: void setConnectionFactoryName(String), void setConnectionFactory(Object)

javax.jdo.option.ConnectionFactory2Name

Get methods: String getConnectionFactory2Name(), Object getConnectionFactory2()

Set methods: void setConnectionFactory2Name(String), void setConnectionFactory2(Object)

javax.jdo.option.ConnectionDriverName

Get method: String getConnectionDriverName( )

Set method: void setConnectionDriverName(String)

7.1.2 Optional Feature Properties

Properties are also available to initialize the settings of the optional features. Specifically, the following transaction properties can be initialized (they are covered in detail in later chapters):

  • javax.jdo.option.NontransactionalRead

  • javax.jdo.option.NontransactionalWrite

  • javax.jdo.option.Optimistic

  • javax.jdo.option.RetainValues

These properties affect the runtime behavior of the application. You can provide a value for these flags when you configure your JDO runtime environment. The flags can be initialized in the Properties object used to construct the PersistenceManagerFactory. If you attempt to set one of these properties to true and the implementation does not support it, a JDOUnsupportedOptionException is thrown.

The following list provides the get and set methods for the optional feature properties:

javax.jdo.option.NontransactionalRead

Get method: boolean getNontransactionalRead()

Set method: void setNontransactionalRead(boolean)

javax.jdo.option.NontransactionalWrite

Get method: boolean getNontransactionalWrite()

Set method: void setNontransactionalWrite(boolean)

javax.jdo.option.Optimistic

Get method: boolean getOptimistic()

Set method: void setOptimistic(boolean)

javax.jdo.option.RetainValues

Get method: boolean getRetainValues()

Set method: void setRetainValues(boolean)

7.1.3 Flags

You can also set some additional flags to control the behavior of your JDO environment. These flags have the following properties, which can be used to configure the PersistenceManagerFactory:

  • javax.jdo.option.IgnoreCache

  • javax.jdo.option.Multithreaded

  • javax.jdo.option.RestoreValues

We discuss Multithreaded and RestoreValues later in this chapter. Chapter 8 and Chapter 9 describe IgnoreCache.

7.1.4 Flags Settings in Multiple Interfaces

Some features have flags that you can get and set to control the behavior of your JDO environment. These flags are maintained in several JDO interfaces. Table 7-2 lists these features and the JDO interfaces that have associated flags and methods for managing their settings.

Table 7-2. Methods to manage flags for features

Feature

Interfaces with methods to get/set flags

NontransactionalRead

PersistenceManagerFactory, Transaction

NontransactionalWrite

PersistenceManagerFactory, Transaction

Optimistic

PersistenceManagerFactory, Transaction

RetainValues

PersistenceManagerFactory, Transaction

RestoreValues

PersistenceManagerFactory, Transaction

IgnoreCache

PersistenceManagerFactory, PersistenceManager, Query

All of these flags have Boolean values. For example, the following methods are defined in Transaction and PersistenceManagerFactory:

void     setOptimistic(boolean flag);
boolean  getOptimistic(  );

If the implementation does not support an optional feature, the value of the associated flag in these interfaces is false. If you attempt to set the flag to true, a JDOUnsupportedOptionException is thrown. For optional features that the implementation does support, it can choose a default value of true or false for the flag. A JDO vendor usually selects a default value most suited to their implementation.

If you want to guarantee that your application behaves consistently across implementations, you should set the values of these flags explicitly (assuming that the implementation supports the feature you wish to enable). Setting a flag to false protects you from unexpected behavior in the future, if the implementation later enables the feature with a default setting of true. You can initialize these flags within the property file that you use to construct the PersistenceManagerFactory.

7.1.5 Determining the Optional Features and Default Flag Settings

You can determine which optional features an implementation supports by calling the following PersistenceManagerFactory method:

Collection supportedOptions(  );

This method returns a Collection of String values, where each element represents an optional feature or query language that the implementation supports. If the implementation does not support an optional feature, this method does not return its associated option string.

The string "javax.jdo.query.JDOQL" indicates that the standard JDO query language is supported. An implementation may also support other query languages; if so, a value is returned to identify each supported query language. These alternative, implementation-specific query languages (and their associated names) are not defined in the JDO specification.

Example 7-1 is a small application that lists the optional features and default flag values for the optional features listed in Table 7-2. It extends the MediaManiaApp class used in Chapter 1. To get the implementation's default values, the property file used to initialize the PersistenceManagerFactory should not initialize the properties. The application calls supportedOptions( ) on line [1] to access the options supported by the implementation. Lines [2] through [7] call PersistenceManagerFactory methods to access the default values for the optional feature flags.

Example 7-1. Getting an implementation's optional features and default flag values
package com.mediamania;

import java.util.Collection;
import java.util.Iterator;
import javax.jdo.PersistenceManagerFactory;

public class GetOptions extends MediaManiaApp {
    
    public static void main(String[] args) {
        GetOptions options = new GetOptions(  );
        options.print(  );
    }

    public void print(  ) {
        Collection options = pmf.supportedOptions();     [1]
        Iterator iter = options.iterator(  );
        System.out.println("Supported options:");
        while ( iter.hasNext(  ) ) {
            String option = (String) iter.next(  );
            System.out.println(option);
        }
        System.out.println("\nDefault values for flags:");
        System.out.print("IgnoreCache           ");
        System.out.println( pmf.getIgnoreCache(  ) );     [2]
        System.out.print("NontransactionalRead  ");
        System.out.println( pmf.getNontransactionalRead(  ) );     [3]
        System.out.print("NontransactionalWrite ");
        System.out.println( pmf.getNontransactionalWrite(  ) );     [4]
        System.out.print("Optimistic            ");
        System.out.println( pmf.getOptimistic(  ) );     [5]
        System.out.print("RestoreValues         ");
        System.out.println( pmf.getRestoreValues(  ) );     [6]
        System.out.print("RetainValues          ");
        System.out.println( pmf.getRetainValues(  ) );     [7]
    }
    public void execute(  ) {
    }
}

Sun's JDO reference implementation produces the following output for this program:

Supported options:
javax.jdo.option.TransientTransactional
javax.jdo.option.NontransactionalRead
javax.jdo.option.NontransactionalWrite
javax.jdo.option.RetainValues
javax.jdo.option.Optimistic
javax.jdo.option.ApplicationIdentity
javax.jdo.option.DatastoreIdentity
javax.jdo.option.ArrayList
javax.jdo.option.HashMap
javax.jdo.option.Hashtable
javax.jdo.option.LinkedList
javax.jdo.option.TreeMap
javax.jdo.option.TreeSet
javax.jdo.option.Vector
javax.jdo.option.Array
javax.jdo.option.NullCollection
javax.jdo.query.JDOQL

Default values for flags:
IgnoreCache           true
NontransactionalRead  true
NontransactionalWrite false
Optimistic            true
RestoreValues         true
RetainValues          true

Notice that all of the flags in Table 7-2 have a setting maintained in a PersistenceManagerFactory instance. When you call getPersistenceManager( ) to construct a PersistenceManager instance, the values of the flags in the PersistenceManagerFactory are copied into the PersistenceManager instance. When you call currentTransaction( ) to access the associated Transaction instance, the transaction-related flags in the Transaction instance get the same values that were set in the PersistenceManagerFactory instance. If you want a flag in the Transaction instance to have a different value, you can call the flag's set method in the Transaction interface. But do not call these methods when a transaction is active.

The value of the IgnoreCache flag in a PersistenceManager affects the behavior of extent iteration and queries. Basically, it determines whether changes you have already made to instances in the application cache should be reflected in extents and the results of queries. The IgnoreCache flag is covered in Chapter 8 and Chapter 9 when we cover extents and queries, respectively.

In a nonmanaged environment, you can use multiple PersistenceManager instances. Each call to PersistenceManagerFactory.getPersistenceManager( ) returns a new instance for your use. You can change the IgnoreCache flag in a PersistenceManager instance. So, it is possible to have two PersistenceManager instances, where one has its IgnoreCache flag set to true, and the other has it set to false.

The IgnoreCache setting in a PersistenceManager establishes the initial value of the IgnoreCache flag in each Query you construct via a call to PersistenceManager.newQuery( ). So, you can construct multiple Query instances and set the values of their respective IgnoreCache flags independently.

7.1.6 Vendor-Specific Properties

A JDO implementation can define its own property keys. You can use the property keys to initialize implementation-specific properties when you configure a PersistenceManagerFactory. Each such property key should have a prefix that associates it with the vendor's implementation. Implementations silently ignore any properties that they do not recognize. If they recognize a property key that they do not support and you specify a value that enables the feature, a JDOFatalUserException is thrown when you call getPersistenceManagerFactory( ).

7.1.7 Nonconfigurable Properties

A JDO vendor may provide nonconfigurable properties and make them available to your application via a Properties instance, which can be retrieved with the following PersistenceManagerFactory method:

Properties getProperties(  );

Each key and value is a String. All JDO implementations support two standard keys:

VendorName

The name of the JDO vendor

VersionNumber

The release number of the vendor's implementation

Other properties returned by getProperties( ) are vendor-specific. This method does not return the configurable properties we covered previously. Your application can modify the returned Properties instance, but the modifications do not affect the behavior of the PersistenceManagerFactory instance.

    [ Team LiB ] Previous Section Next Section