A user can create her own subclass of Configuration and use it instead of the classes provided by Cayenne. Custom subclasses are usually created to load configuration files from non-standard locations, to automatically configure Cayenne during certain events that happen in deployment containers, etc. Cayenne provides a few implementations of Configuration discussed later in this chapter.

To ensure that Cayenne uses the correct Configuration class, it must be initialized properly before any calls to Configuration are made:

import org.objectstyle.cayenne.conf.Configuration
...
Class myConfigSubclass = my.package.ConfigSubclass.class;
Configuration.initializeSharedConfiguration(myConfigSubclass);

After this code is executed, any subsequent calls to Configuration.getSharedConfiguration() will return an instance of the custom class instead of DefaultConfiguration.

Another useful feature is the customization of the resource lookup strategy implemented by the existing classes. Currently, both DefaultConfiguration and FileConfiguration offer the possibility to add additional paths which will be searched for resources.

DefaultConfiguration

DefaultConfiguration uses the application's class path for locating configuration files; this works for both "expanded" class paths and JAR files. "Out of the box" only resources on the top level of the class path are found; very often it is convenient to have a subdirectory ('package') with configuration files. There are two ways to make Configuration find these files:

import org.objectstyle.cayenne.conf.DefaultConfiguration;
...
DefaultConfiguration conf = new DefaultConfiguration();			
conf.addClassPath("my/package/conf");
Configuration.initializeSharedConfiguration(conf);

Alternatively you can place an empty subclass of DefaultConfiguration into your package and use that class directly:

import my.package.conf.MyPackageConfiguration;
...
Configuration.initializeSharedConfiguration(new MyPackageConfiguration());

FileConfiguration

FileConfiguration uses the regular file system to load its files, and works very silimar to DefaultConfiguration:

import org.objectstyle.cayenne.conf.FileConfiguration;
...
String fileName = "/some/path/to/my-cayenne.xml";
FileConfiguration conf = new FileConfiguration(new File(fileName));
Configuration.initializeSharedConfiguration(conf);

The fileName argument can be absolute or relative to the application's working directory, and is checked for accessibility. A more flexible lookup can be done by using the name without any path and adding search paths:

import org.objectstyle.cayenne.conf.FileConfiguration;
...
FileConfiguration conf = new FileConfiguration("my-cayenne.xml");
conf.addFilesystemPath("a/relative/path");
conf.addFilesystemPath("/another/absolute/path");
conf.addFilesystemPath(new File("/some/path/that/must/exist/"));
Configuration.initializeSharedConfiguration(conf);

The difference between the String and File arguments is that the latter are checked for existence. Both variants can be absolute or relative, and are evaluated in the order in which they are added to the Configuration.