In this topic
- About implementing a class extension
- Develop a class extension
- Deploy a class extension
- Apply a class extension
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:
- IObjectClassValidation—Implements custom attribute validation
- IObjectClassEvents—Implements custom object event behavior
- IRelatedObjectClassEvents and IRelatedObjectClassEvents2—Implement custom relationship behavior
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.
//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 to ArcGIS for Desktop (ArcMap or ArcCatalog), copy the JAR file containing the extension to <ArcGIS Desktop Install Dir>/java/lib/ext folder and restart the Desktop application. To deploy class extension to ArcGIS for Server, place the file in <ArcGIS Server Install Dir>/usr/lib/ext folder and restart Server. This will deploy the extension to the appropriate ArcGIS environment.
The class extension must then be enabled or applied on the geodatabase feature class of choice programmatically (as described in the following section). If the class extension source is modified at any time, it must then be redeployed following above mentioned steps, for the changes to take effect.
Enabling 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.
The ArcObjects Java SDK includes several samples that demonstrate enabling class extensions. Please consult any one of the following samples to understand API usage:
- $AGSDEVKITJAVA/java/samples/arcobjects/geodatabase/featureclassextension/featurevalidation
- $AGSDEVKITJAVA/java/samples/arcobjects/geodatabase/featureclassextension/relatedobjecteventhandler
- $AGSDEVKITJAVA/java/samples/arcobjects/geodatabase/featureclassextension/timestamper
Note that when executing class extensions in Server environment, the esriLicenseProductCode.esriLicenseProductCodeArcServer license must be used.
As a note of caution, any geodatabase that includes a feature class with a class extension enabled will remain accessible only when the class extension is present and registered. Therefore, if you move a feature class with a class extension enabled to another ArcGIS environment (for ex: Server to Desktop or Engine) or geodatabase, ensure that the destination environment or geodatabase too has the class extension registered.
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 validationCustomize object event behavior
Customize relationship behavior
Development licensing | Deployment licensing |
---|---|
Engine Developer Kit | ArcInfo |
ArcEditor | |
ArcView | |
Engine Runtime | |
Server |