[ Team LiB ] |
7.1 Configuring a PersistenceManagerFactoryA 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.
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 PropertiesThe following connection properties are used to configure a datastore connection:
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:
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:
The following list provides the get and set methods for each of the connection properties:
7.1.2 Optional Feature PropertiesProperties 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):
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:
7.1.3 FlagsYou 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:
We discuss Multithreaded and RestoreValues later in this chapter. Chapter 8 and Chapter 9 describe IgnoreCache. 7.1.4 Flags Settings in Multiple InterfacesSome 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.
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 SettingsYou 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 valuespackage 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 PropertiesA 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 PropertiesA 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:
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 ] |