This page last changed on Nov 08, 2010 by simboss.

Overview

Adding a new configuration subsystem that is easier to maintain and more effective then the one currently in place.

Proposed By

Justin Deoliveira
Jody Garnett

Proposal Type

Core Module Change

Assigned to release

1.7.0

State

Accepted

Links

JIRA task: http://jira.codehaus.org/browse/GEOS-1951

Email discussion: http://www.nabble.com/new-configuration-gsip-reworked-td17379978.html

Other wiki discussions:

Voting History

PSC:

Motivations

The current configuration is cumbersome for programmers. A simple change to a configuration parameter can require the changing of up to 3 classes. Furthermore, each "config object" is duplicated with a "data transfer object" which is used to capture its properties" during persistence.

Furthermore the current config objects have become somewhat messy. Coming up with an api which is more "bean like", and consistent in terms of naming conventions for properties will produce a nicer api to work with.

Proposal

Implementing the new configuration falls into 3 primary phases:

  1. Coming up with a new configuration model
  2. Wrapping up the new configuration in the old one
  3. Fully porting the rest of the code base to the new model

Phase 1: New Configuration Model

This phase is more or less complete. An in depth description of the new model can be found here:

Phase 2: Porting Old Model to New Model

The new configuration model is inspired by the old model, and the core classes or more less the same. Wrapping up the new model objects in the old objects is straight forward. The main benefit of such an approach is that it remains backwards compatible with the rest of GeoServer. This allows us to keep the user interface, persistence layer, and services all untouched.

The following diagram illustrates the way things currently work today:

The following diagram illustrates the proposed changes. Essentially ripping out the internals of the "global" tier and replacing it with the new model.

At the code level the work boils down to removing all properties from the old config objects and having all methods call though to associated new objects. For example, consider the following subset of the FeatureTypeInfo object.

BEFORE:

package org.vfny.geoserver.global;

class FeatureTypeInfo {

  String name;
  String abstract;
  ...

  String getName() {
     return name;
  }

  void setName( String name ) {

  }

  String getAbstract() {
     return abstract;
  }

  void setAbstract( String abstract) {
     this.abstract = abstract;
  }

  ...   
  
}

AFTER:

package org.vfny.geoserver.global;

@deprecated use {@link org.geoserver.catalog.FeatureTypeInfo}
class FeatureTypeInfo {

  org.geoserver.catalog.FeatureTypeInfo delegate;

  String getName() {
     return delegate.getName();
  }

  void setName( String name ) {
     delegate.setName( name );
  }

  String getAbstract() {
     return delegate.getAbstract();
  }

  void setAbstract( String abstract) {
     delegate.setAbstract( abstract );
  }

  ...   
  
}

This process is repeated for all config objects. The following mappings are made:

old new
org.geoserver.vfny.global.Data org.geoserver.catalog.Catalog
org.geoserver.vfny.global.DataStoreInfo org.geoserver.catalog.DataStoreInfo
org.geoserver.vfny.global.FeatureTypeInfo org.geoserver.catalog.FeatureTypeInfo
org.geoserver.vfny.global.CoverageStoreInfo org.geoserver.catalog.CoverageStoreInfo
org.geoserver.vfny.global.CoverageInfo org.geoserver.catalog.CoverageInfo
org.geoserver.vfny.global.NameSpaceInfo org.geoserver.catalog.NamespaceInfo
org.geoserver.vfny.global.GeoServer org.geoserver.config.GeoServerInfo
org.geoserver.vfny.global.Service org.geoserver.config.ServiceInfo
org.geoserver.vfny.global.WMS org.geoserver.wms.WMSInfo
org.geoserver.vfny.global.WCS org.geoserver.wcs.WCSInfo
org.geoserver.vfny.global.WFS org.geoserver.wfs.WFSInfo

Phase 3: Porting Code Base to New Model

This phase involves porting the rest of the code base to the new model. This involves services and the ui. At this point the persistence model can be swapped out by one that is easier to maintain and which automatically persists the configuration beans.

See the following page for details:

Summary of Changes

Mappings

As described in the previous section

ResourcePool

In the old configuration model, the "info" objects are responsible for loading resources like geotools datastores, feature types, coverage readers, and styles. For an example see FeatureTypeInfo.getFeatureSource(). This poses a number of difficulties:

  • It makes automatically persisting them hard. "Derived" properties are harder to persist than regular properties.
  • It requires the objects to live in memory since creating the underlying resources is expensive. One of the requirements of the new configuration system is to have it back onto a peristence layer like hibernate. One cannot make the assumption that an object will stay in memory with an OR mapper.
  • A mix of java bean + resource loading is messy. Especially when you start implementing caching of resources.

For this reason a class dedicated to loading resources is created called ResourcePool. It seperates all the source handling code away from the configuration beans. Consider DataStoreInfo:

BEFORE:

class DataStoreInfo {

  DataStore dataStore;

  ...

  DataStore getDataStore() {


     if ( dataStore != null ) {
        return dataStore;
     }


     //grab the datastore factory
     DataStoreFactory factory = DataStoreFactory.aquire( connectionParams );

     //create the datastore 
     dataStore = factory.createDataStore(connectionParams );

     return datastore;
  }
}

AFTER:

class DataStoreInfo {

  Catalog catalog;
 
  ...

  DataStore getDataStore() {
     return catalog.getResourcePool().getDataStore( this );
  }
}

The ResourcePool object is a singleton, and stays around for the life of the GeoServer instance.

Configuration Loading

On system startup and on subsequent configuration loads the configuration stored on disk must be read into an instance of the new model. The following classes have been added:

LegacyConfigurationImporter, LegacyCatalogImporter

Reads the services.xml, catalog.xml and info.xml files into instances of the new model. In GeoServer 2.x when we change the persistence layer these classes will be used as a utility to support loading of GeoServer 1.x configurations.

GeoServerLoader

Runs on startup and delegates to the above two classes to initialize the configuration system. This class also has a shutdown hook which will be used to persist the configuration system when the persistence layer is changed.

ServiceLoader

An extension point for loading service configurations. This allows the core configuration system to not have to know about services which have been plugged in. There are currently three implements: WFSLoader, WMSLoader, and WCSLoader.

GeoServerInitalizer

An extension point interface uses to initialize based on GeoServer configuration. This extension point is processed by GeoServerLoader after the configuration is read. See the next section about Logging and JAI initialization.

Logging and JAI Initialization

In the current system initializing of these sub systems occurs in static methods on org.vfny.geoserver.GeoServer. IN the new model this class is a strict java bean so this type of system initialization is out of place. The equivalent has been implemented as instances of the GeoServerInitializer extension point. These implementations use the new configuration system event model to keep in sync when users change configuration via the user interface.

Backwards Compatibility Issues

Risks

This type of core change of course has the potential for a number of regressions. The best way to address this is rigorous testing.

Unit Tests

Passing of all existing unit tests without making any changes to the unit tests themselves.

CITE Tests

Hand Testing

Extensive hand testing of the user interface. This involves testing the change, saving, and reloading of every single configuration option in the user interface (painful i know).

Participants

Justin Deoliveira
Andrea Aime
Jody Garnett


configurationPersistence.svg (image/svg+xml)
configurationPersistence.png (image/png)
GeoServerMetaData.java (text/x-java)
FeatureTypeInfo.java (text/x-java)
DataStoreInfo.java (text/x-java)
FeatureTypeInfo.java (text/x-java)
GeoServerMetaData.java (text/x-java)
DataStoreInfo.java (text/x-java)
DataStoreInfo.java (text/x-java)
data.zip (application/zip)
org.geoserver.data.png (image/png)
new.png (image/png)
old.png (image/png)

Generally I'm for it. My one concern is config file backwards compatibility. I'm fine to break it once - we just call it GeoServer 2.0. Though we should acknowledge that's a major change - the backwards compatibility issues section kind of discounts that. I'd almost say that config file compatibility is the more important one than the code, as it's the one users see.

But we can call it GS 2.0, and that's fine. But have we done tests to ensure that if we add a new field to one of the core beans XStream will still be able to read a config made with an older version of GeoServer?

That was actually the problem with the old, old way of reading config, done with Castor I think. It would do nice persistence from our core objects, but if we changed those objects at all then it couldn't read the old versions. So will XStream work if it doesn't find the new options? Just populating those with the defaults and not blow up? I mean, I'd be surprised if it didn't, but I want to be 100% sure before we commit to this technology, or any technology.

Posted by cholmes at Jan 25, 2007 13:01
Document generated by Confluence on May 14, 2014 23:00