How to implement a class extension


In this topic


About implementing a class extension

Class extensions are implemented to define complex custom data behavior in a geodatabase. Class extensions are Java extension classes that are developed using the ArcObjects application programming interface (API) and deployed to ArcGIS. Class extensions that are deployed to ArcGIS must be applied to object classes (tables) or feature classes in a geodatabase programmatically to enforce the custom data behavior.
For more information about class extensions, see Getting started with class extensions.  

Develop a class extension

A class extension is a Plain Old Java Object (POJO) that implements specific interfaces and is annotated with @ArcGISExtension. This section describes how to develop a class extension.

Create a Java class

Create a Java Class for a class extension that implements, at a minimum, the IClassExtension and IObjectClassExtension interfaces. If the extension is designed for feature classes, implement the IFeatureClassExtension interface too. IClassExtension is the only required interface; IObjectClassExtension and IFeatureClassExtension are indicator interfaces that do not have method definitions to implement. 
The custom data behavior of a class extension is defined by implementing additional interfaces. The Java class must implement one or more of the following interfaces depending on the custom behavior implemented by the class extension:
For more information about implementing these interfaces, see the following topics:

Annotate a Java class

When the class extension is developed and deployed to an ArcGIS client, the ArcGIS runtime recognizes the Java class as a custom object by its @ArcGISExtension annotation. It is essential that you annotate the Java class with @ArcGISExtension annotation and set its category attribute as ArcGISCategories.GeoObjectClassExtensions. 
The following code snippet shows how the Java class is annotated with @ArcGISExtension:
[Java]
//Create a Java class.
//Annotate the Java class.
@ArcGISExtension(categories = {
    ArcGISCategories.GeoObjectClassExtensions
}

)public class FirstClassExtension implements IClassExtension, IObjectClassExtension,
    IFeatureClassExtension{}

Add implementation code

Add implementation code to the init and shutdown methods of the IClassExtension interface. These methods are described as follows:
  • init—This method is invoked by the ArcGIS runtime when the class extension is initialized. Class extensions are initialized when they are applied to an existing class or when their applied class is accessed by an ArcGIS client. When invoking the init() method, the ArcGIS framework provides the following parameter references that can be crucial for other methods to operate correctly: 
    • IClassHelper—The class helper parameter provides the object reference of the object or feature class to which the class extension is applied. Many extensions require an object reference. For example, with the init() method, the class helper parameter provides reference to the feature table to which the class extension is applied. The reference parameter allows you to access the properties of the feature class and its attributes and values.
    • IPropertySet—The property set parameter contains the properties of the class extension with regard to the applied object or feature class. These properties can include strings, images, and other objects that are relevant to implementation of the class extension. The properties are persisted to the geodatabase as metadata on a class-by-class basis for each table or feature class to which the class extension is applied. This allows each class extension table or feature class to be configured individually. 
      Property values can be modified at any time by casting the object class reference to the IClassSchemaEdit2 interface and calling the alterClassExtensionProperties method with a new set of properties as a parameter. As with other methods in the IClassSchemaEdit interface, you need to obtain an exclusive schema lock for the class prior to modifying its extension properties. When an object or feature class with an associated class extension is created, it has no extension properties and the value passed to the IClassExtension.init() method's parameter is null. If properties are required for the extension to operate correctly, the init() method can check whether the incoming property set is null, and if so, apply a default set of properties and persist the property values by invoking the IClassSchemaEdit2.alterClassExtensionProperties() method.
  • shutdown—This method is called when its associated object or feature class is disposed of or when the extensions are removed from the class.
A class extension is instantiated and disposed of in parallel with the lifespan of the object or feature class to which it is applied in memory.
The following code snippet implements a skeleton class extension. The data behavior of the class extension is implemented through interfaces such as IObjectClassValidation, IObjectClassEvents, IRelatedObjectClassEvents, and IRelatedObjectClassEvents2 and is not shown in the code. The code snippet does show the following in the init() method implementation: 
  • The string values of the CREATED_FIELD_PROPERTY and MODIFIED_FIELD_PROPERTY class variables are the properties of the class extension. You can determine the value of the properties by using IPropertySet.getProperty(). You can also alter the property values using IPropertySet.setProperty() and persist the properties to their object class using IClassSchemaEdit2.alterClassExtensionProperties().
  • The object reference to which the class extension is applied is derived from the class helper parameter using the IClassHelper.esri_getClass() method.
[Java]
//Declare class variables.
// The property set keys are used to get and set the extension properties.
public final static String CREATED_FIELD_PROPERTY = "CREATION_FIELDNAME";
public final static String MODIFIED_FIELD_PROPERTY = "MODIFICATION_FIELDNAME";

// Use the default field names as timestamp fields if none are defined when the
//class extension is applied.
private final static String DEFAULT_CREATED_FIELD = "CREATED";
private final static String DEFAULT_MODIFIED_FIELD = "MODIFIED";

/**
 * The indexes of the timestamp fields in the extension class. A value of -1 indicates
 * that the field is not used or could not be found during initialization.
 */
private int createdFieldIndex =  - 1;
private int modifiedFieldIndex =  - 1;

/************************************************************************************************
 * IClassExtension members
 ************************************************************************************************/

// Initialize the extension, passing in a reference to its class helper and its extension properties.

public void init(IClassHelper classHelper, IPropertySet extensionProperties)throws
    IOException, AutomationException{
    // Get a reference to the extension's object class.
    IClass baseClass = classHelper.esri_getClass();
    // Make sure a valid property set is provided.
    if (extensionProperties != null && extensionProperties.getCount() != 0){
        // Get the field names from the property set.
        Object createdFieldProperty = extensionProperties.getProperty
            (CREATED_FIELD_PROPERTY);
        Object modifiedFieldProperty = extensionProperties.getProperty
            (MODIFIED_FIELD_PROPERTY);

        // Get the created field index.
        if (createdFieldProperty != null){
            createdFieldIndex = baseClass.findField(createdFieldProperty.toString());
        }
        // Get the modified field index.
        if (modifiedFieldProperty != null){
            modifiedFieldIndex = baseClass.findField(modifiedFieldProperty.toString()
                );
        }
    }
    else{
        // If the extension properties are null or empty, assume the class has
        // been created without extension properties. Apply the default property values.
        ISchemaLock schemaLock = null;
        try{
            // Attempt to acquire an exclusive schema lock. If this fails, an
            // AutomationException will be raised.
            schemaLock = new ISchemaLockProxy(classHelper.esri_getClass());
            schemaLock.changeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
            // Create a default set of extension properties.
            IPropertySet propertySet = new PropertySet();
            propertySet.setProperty(CREATED_FIELD_PROPERTY, DEFAULT_CREATED_FIELD);
            propertySet.setProperty(MODIFIED_FIELD_PROPERTY, DEFAULT_MODIFIED_FIELD);
            // Use the IClassSchemaEdit2 interface to persist a new set of extension properties.
            IClassSchemaEdit2 classSchemaEdit2 = new IClassSchemaEdit2Proxy
                (classHelper.esri_getClass());
            classSchemaEdit2.alterClassExtensionProperties(propertySet);
        }
        catch (AutomationException autoExc){
            // An exclusive schema lock could not be acquired. Allow the extension to
            // finish initializing; no custom behavior will occur.
        }
        finally{
            try{
                // Ensure that the schema lock is shared.
                if (schemaLock != null)
                    schemaLock.changeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
            }
            catch (Exception exc){
                // Ignore any errors at this point.
            }
        }
    }
}

/**
 * Called when the extension's class is being disposed of from memory.
 */
public void shutdown()throws IOException, AutomationException{
    // Do nothing.
}

Export as a JAR file

The class extension Java class must be deployed to ArcGIS. To deploy the class extension, the class files of the Java classes are bundled as a Java Archive (JAR) file.
For more information about creating a JAR file, see How to export a custom geoprocessing tool.

Deploy a class extension

To deploy the class extension, move the JAR file to the <ArcGIS Install Dir>/java/lib/ext folder of the ArcGIS client accessing the object or feature class or applying the class extension. The ArcGIS client (ArcMap, ArcCatalog, ArcGIS Engine application, or ArcGIS Server application) recognizes the class extension when the client is started. If the client is already running, restart it after the class extension is deployed. When testing the class extensions, if you modify the code in any of the Java classes bundled in the JAR file, you must recreate the JAR file and redeploy the class extension. Restart the ArcGIS application after redeployment as well.

Apply a class extension

When the class extension is developed and deployed, there are a couple of ways to apply the extension to an object class (table) or feature class, depending on whether the class already exists and whether the extension is applied through an application or programmatically. Use one of the following options to apply a class extension: 
  • To apply an extension when creating new object or feature classes, pass a fully qualified class name of the annotated Java class of the class extension to the IFeatureWorkspace.createTable() or IFeatureWorkspace.createFeatureClass() method.
  • To apply an extension to an existing class, invoke the IClassSchemaEdit.alterClassExtensionCLSID() method programmatically and pass the fully qualified class name of the annotated Java class of the class extension. This method can also be used to remove a class extension by providing null values as parameters.
When a class extension is applied to an object or feature class, the required information pertaining to the class extension is stored at the geodatabase level. The class extension must be deployed to an ArcGIS client to access the object or feature class to which the class extension is applied. If the applied class extension failed, is flawed, or does not deploy at the ArcGIS client, the corresponding object or feature class cannot be accessed through ArcGIS until the class extension is removed. For more information about applying extensions, see Apply class extensions.
A class extension can be applied to one or more objects or feature classes in a geodatabase; however, only one class extension can be applied to an object or feature class at any given time.


See Also:

Customize attribute validation
Customize object event behavior
Customize relationship behavior
Apply class extensions