db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "David W. Van Couvering" <David.Vancouver...@Sun.COM>
Subject VOTE: Shared Components Guidelines (with guidelines inlined)
Date Sat, 22 Oct 2005 00:07:54 GMT
Hi, all, here is the vote for the shared components guidelines following 
the ASF standard of including the full text of the item being voted for 
in the email.

These guidelines will be accessible from the Derby Wiki page at


The guidelines as shown here reflect version 29 of this Wiki page. 
Version 29 can be directly viewed at


Changes since the last call for a vote can be seen by looking at





This document describes our guidelines around shared components in 
Derby, where a shared component is a collection of one or more packages 
that is used across multiple subsystems within Derby. Very loosely, I 
would define a "subsystem" as the code contained in one of the top-level 
source directories, e.g. engine, client, drda, tools, etc. As of this 
writing, the only shared component like this is the proposed common code 
component (see [WWW] DERBY-289). Other components may be defined in the 
future as needed (for example, perhaps the DRDA networking code should 
be separated out as an independent shared component).

The guidelines for shared components in Derby are based on the [WWW] 
Jakarta Runtime Versioning Guidelines. There are some areas that these 
guidelines do not cover, however, which we will address here:

    1. Mixed Version Support
    2. Guidelines for Forward Compatibility
    3. Deprecation Guidelines
    4. Location and Distribution of Shared Components
    5. Documenting Shared Components
    6. User Visible Impact and Restrictions
    7. Testing Impact
    8. Introducing New Shared Components and Shared Packages

Two applications should be able to use one version of the Derby network 
client driver and a different version of the Derby embedded driver 
within the same Java VM without having to resort to creating specialized 
classloaders. This is enabled by supporting forward compatibility as 
described below.

A consumer built against version X.Y of a shared component should work 
with version X.Y' of a module where Y' < Y. This is called forward 

If the consumer uses new functionality added in version X.Y of the 
module, it should degrade to X.Y' level functionality. In the rare cases 
where this is not achievable, the consumer should throw an exception 
explaining that it requires version X.Y or greater of the shared 
component (rather than an obtuse Java exception like NoSuchMethodException).

Forward compatibility must be guaranteed between patch revisions (from 
X.Y.Z to X.Y.Z') and minor revisions (from X.Y to X.Y'). We should 
strive for forward compatibility between major releases, but it is not a 

The consumer decides it can work with a given version of a shared 
component not by looking up its version number and then extrapolating 
what features are available, but instead by directly querying the 
component to see if the shared component provides the feature or 
features it is looking for.

A shared component must provide a class called <ComponentName>Info that 
provides a static method called hasFeature. This class should be at the 
top level of the package for that component, e.g. the info class for the 
common component should be org.apache.derby.common.CommonInfo.

This method takes a single parameter which is a feature identifier. If 
the shared component implementation recognizes the feature identifier, 
it returns true, otherwise it returns false. Here is an example 
definition and usage using the common component. Assume that a consumer 
is making use of a new whizbang feature in the message utilities in a 
newer version of the common component which is not available in older 

Here is the old version of the CommonInfo class:

    2 public static class CommonInfo
    3 {
    4   public static final int COOL_FEATURE = 1;
    5   private static final int MAX_FEATURE = COOL_FEATURE;
    7   public static boolean hasFeature(int featureId)
    8   {
    9       return featureID <= MAX_FEATURE;
   10   }
   11 }

Here is the new definition of the CommonInfo class:

    2 public static class CommonInfo
    3 {
    4   public static final int COOL_FEATURE = 1;
    5   public static final int WHIZBANG_FEATURE = 2;
    6   private static final int MAX_FEATURE = WHIZBANG_FEATURE;
    8   public static boolean hasFeature(int featureId)
    9   {
   10       return featureID <= MAX_FEATURE;
   11   }
   12 }

The consumer is then built with the new common component and uses the 
new CommonInfo class definition:

    2 if ( CommonInfo.hasFeature(CommonInfo.WHIZBANG_FEATURE) )
    3 {
    4   // use whizbang feature
    5 }
    6 else
    7 {
    8   // use older mechanism
    9 }

Note that the constant CommonInfo.WHIZBANG_FEATURE is compiled down to a 
constant integer, so there will not be runtime errors if the older 
version of the component has been loaded.

A method or an interface may be deprecated. This is done using the 
@deprecated tag in the method or interface Javadoc. A method or 
interface must be available for 2 major releases after it is deprecated. 
For example, if it is deprecated in version 8.2, it can be removed in 
version 10.0 or greater. An exception to this rule may occur if it 
becomes clear that there is still heavy use of this interface.

All shared components should comprise of one or more packages under the 
package org.apache.derby.common (stored in the source tree under 

Although it would be conceptually nice to have a separate JAR file for 
each shared component, it is a priority for us to keep a very simple 
user experience. For this reason, the classes of a shared components 
will be merged into the appropriate subset of the existing jar files.

We will provide a top-level package.html javadoc under 
java/org/apache/derby/common that describes the shared components 
guidelines (once they are approved) and lists the available components. 
For each shared component we will provide:

     * Name of component
     * Description of component (its role or intent)
     * Packages contained within the component
     * The name of the Info class that provides the hasFeature() method

With these guidelines in place, there will be no visible impact or 
restrictions for Derby users.

No visible impact implies the following checkin requirements for any 
common code.

     * Derby jar files of the same major version can continue to be 
mixed within the same JVM classpath without any difference in behavior 
from loading these jars in separate classloaders.
     * Jar file growth is commensurate with functionality improvement.
     * Replacing any jar with a jar of the same major version will not 
require any user classpath changes.

The only exception is if for some reason (and this is to be avoided) a 
change is made between major revisions that is not compatible, then if 
the user is running in a mixed version environment in the same VM, he or 
she should attempt to ensure that the jar files from the newer version 
are loaded first. If for some reason this is not possible, the user will 
need to separate the two versions by using separate classloaders within 
the same VM.

In the first new release after common components are introduced, we will 
want to test for compatibility between patch and minor releases in the 
following ways:

     * Build common component unit tests against the new release and 
test against jar files from old releases (backward compatibility tests)
     * Build common component unit tests from old releases and test 
against jar files from the new release (forward compatibility tests)

Any incompatibilities introduced between patch and minor releases should 
be considered a regression. Any incompatibilities between major releases 
should be documented.

When a developer wishes to introduce a new shared component or a new 
package within an existing shared component, this should be put up for a 
vote. This is to help ensure that what we are sharing makes sense and 
does not accidentally paint us into some kind of architectural corner. 
Adding new classes or methods to an existing shared package does not 
need to be put up for a vote but should be reviewed using the standard 
patch review mechanism.

View raw message