Utility Objects


Summary Utility Objects are Java extensions that can be used to improve performance of ArcGIS Server and ArcGIS Engine applications. Quite commonly, applications that make lots of fine-grained ArcObjects calls across process or thread boundaries tend to suffer from poor performance because of the cost of round trips incurred by the calls. Utility Objects are used to eliminate these cross-context calls and improve application performance.

This walkthrough describes the steps for writing a Utility Object in Java that can be consumed in ArcGIS Server applications (over local connection) and ArcGIS Engine applications.

In this topic


About Utility Object

A Utility Object is a Java extension that encapsulates GIS functionality that is achieved by making fine-grained ArcObjects calls and exposes that functionality through a coarse-grained API, ensuring that the fine-grained ArcObjects calls do not cross process or thread boundaries.  Utility Objects are used to improve performance of ArcGIS Server and ArcGIS Engine applications. Quite commonly, applications that make lots of fine-grained ArcObjects calls across process or thread boundaries tend to suffer from poor performance because of the cost of round trips incurred by the calls. Utility Objects are used to eliminate these cross-context calls and hence improve application performance.
Extending ArcGIS Server with utility objects allows you, as a developer, to easily share your components across the ArcGIS developer products, i.e. ArcGIS Server and ArcGIS Engine.  These utility objects do not need to be tied to any particular Server Object configuration or type, and may even be used in an empty server context.  This strategy does have some limitations. When extending the GIS server with a utility object, the object must be created new for each request made on a particular Server Object or context. This means that for pooled Server Object’s, each time a request is made the utility object must be created, which can be effect performance if there is a high initialization cost.  Because the object is created for each request, you can't use it to cache information through its lifecycle.
 
A major advantage of Utility Objects is that it can be used to alleviate performance problems caused by the overhead of making fine-grained ArcObjects calls across threads (between Java threads and ArcObjects thread) in UI-based ArcGIS Engine applications.

When are Utility Objects used

One of the uses of Utility Objects is to solve a particular class of performance problems that could affect ArcGIS Server and User Interface-based ArcGIS Engine applications.
These performance problems are the result of the overhead incurred in making fine-grained ArcObjects calls across processes (between the Web-server and the GIS Server) in Server applications and across threads (between Java threads and ArcObjects thread) in UI-based Engine applications.
Utility objects provide a logical solution to such problems by preventing fine-grained calls across contexts, ensuring that these calls execute within the GIS Server process (as opposed to the Web Server) in ArcGIS Server applications and within the ArcObjects thread (as opposed to Java threads) in UI-based Engine applications.

Writing a Utility Object

The following steps describe the procedure for writing a Utility Object. Note that these procedural steps are the same regardless of the client application (whether Server or Engine) that will consume the Utility Object.
Step 1: Define a custom interface(s)
An implementer of the Utility Object should define a custom interface that describes an API for clients to call methods on it. One ought to bear in mind that only a permitted list of data types can a custom interface use in its method definitions. They are listed below:
  • All Java primitive types except primitive characters (“char”).
  • Single-dimensional array of all Java primitive types except primitive characters (“char”)
  • Java String types
  • Single-dimensional array of Java String types
  • ArcObjects Interface types
  • Single-dimensional array of ArcObjects Interface types
To qualify as being part of an ArcGIS Java extension the custom interface needs to be decorated with the @ArcGISExtension annotation.
The following code snippet shows an example of a custom interface that declares a single method that will compute the total area of features in a feature layer.  
[Java]
@ArcGISExtension 
// Custom Interface
public interface ICalculateArea{
    public double calculateArea(IFeatureLayer featureLayer)throws IOException,
        AutomationException;
}
Step 2: Define a Java class that implements the custom interface(s)
 
For ArcGIS to recognize this class as a Java extension it needs to be decorated with the @ArcGISExtension annotation. See code snippet below.
[Java]
@ArcGISExtension 
// Decorated with annotation
public class CalcAreaUtil implements ICalculateArea{}
Step 3: Implement the custom interface(s)
The Utility Object should now implement all of the custom interface(s) it has defined.
The following snippet shows an implementation of the “calculateArea” method declared on the custom interface ICalculateArea. The implementation iterates through all the features in a feature class to compute the total area.
[Java]
public double calculateArea(IFeatureLayer featureLayer){
    double totalArea = 0;
    // Obtain the feature class 
    IFeatureClass featureClass = featureLayer.getFeatureClass();
    int numFeatures = featureClass.featureCount(null);
    IFeatureCursor featureCursor = featureLayer.search(null, true);

    IFeature feature = null;
    Polygon polygon = null;
    for (int i = 0; i < numFeatures; i++){
        feature = featureCursor.nextFeature();
        polygon = (Polygon)feature.getShape();
        totalArea += polygon.getArea();
    }
    return totalArea;
}
Step 4: Deploy the Utility object
Once authored, the Utility object needs to be exported to a jar file, which is the deployment unit for ArcGIS Java extensions. At this time, any external dependencies/libraries needed by the Utility object should be specified in a manifest file and bundled with the jar file containing the extension. For details on how to create a manifest file to indicate jar file/class files dependencies, please refer to Sun’s documentation on this subject. 
Once exported to a jar file, the Utility Object needs to be deployed to ArcGIS, for clients to start using it. There are two ways of deployment.
  1. Copy the jar file to the ARCGISHOME/java/lib/ext folder. This ensures that the extension gets automatically registered with ArcGIS when the application starts up the next time. This is a Java-friendly way and a recommended practice for deploying all ArcGIS extensions.
  2. Explicitly register the jar with ArcGIS either through the API exposed on the com.esri.arcgis.interop.extn.RegTool class or through the “regtool.bat”/”regtool.sh” script available under ARCGISHOME/java/tools.

Consuming the Utility Object

Once deployed, the Utility Object can be consumed from an Engine/Server application in the following manner. The code snippet below illustrates how to create an instance of a Utility Object and call the “calculateArea” method on it, passing in the 2’nd layer of the map document as its argument.
Engine:
[Java]
IFeatureLayer featureLayer = mapServer.getLayer(" ", 2);
ICalculateArea calArea = (ICalculateArea)
    com.esri.arcgis.system.EngineContext.createObject(CalcAreaUtil.class);
double totalArea = calArea.calculateArea(featureLayer);
Server:
 
 
[Java]
IFeatureLayer featureLayer = mapServer.getLayer(" ", 2);
ICalculateArea calArea = (ICalculateArea)
    com.esri.arcgis.server.ServerContext.createObject(CalcAreaUtil.class);
double totalArea = calArea.calculateArea(featureLayer);
A sample Engine application is available to illustrate the two approaches –1. fine-grained ArcObjects and 2. Utility Object – to compute the total area of all features in a particular layer and shows a performance comparison between the two approaches.


See Also:

Server Object Extension
Sample: Scenario.UtilityObject




Development licensing Deployment licensing
Engine Developer Kit Engine Runtime
Server Server