Utility objects


Summary
Utility objects are Java extensions that can be used to improve performance of ArcGIS for Server and ArcGIS Engine applications. Typically, 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 topic describes the steps for writing a utility object in Java that can be consumed in ArcGIS for Server applications (over a local connection) and ArcGIS Engine applications.

In this topic


About utility objects

A utility object is a Java extension that encapsulates geographic information system (GIS) functionality that is achieved by making fine-grained ArcObjects calls and exposes that functionality through a coarse-grained application user interface (API), ensuring that the fine-grained ArcObjects calls do not cross process or thread boundaries.  Utility objects are used to improve performance of ArcGIS for Server and ArcGIS Engine applications. Typically, 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 for Server with utility objects allows you to easily share your components across the ArcGIS developer products, such as ArcGIS for Server and ArcGIS Engine.  These utility objects do not need to be tied to any particular server object configuration or type and can 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 for each request made on a particular server object or context. This means that for pooled server objects, each time a request is made, the utility object must be created, which can affect 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 they can be used to alleviate performance problems caused by the overhead of making fine-grained ArcObjects calls across threads (between Java threads and ArcObjects threads) in user interface-based ArcGIS Engine applications.

Using utility objects

One of the uses of utility objects is to solve a particular class of performance problems that could affect ArcGIS for 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 ArcGIS for Server applications and across threads (between Java threads and ArcObjects threads) in user interface-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 for Server applications and within the ArcObjects thread (as opposed to Java threads) in user inteface-based Engine applications.

Writing a utility object

The following steps describe the procedure for writing a utility object. These procedural steps are the same regardless of the client application (whether Server or Engine) that will consume the utility object.

Defining a custom interface

An implementer of the utility pbject should define a custom interface that describes an API for clients to call methods on it. A custom interface can only use the following permitted data types in its method definitions:
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 computes the total area of features in a feature layer:
[Java]
@ArcGISExtension 
// Custom interface.
public interface ICalculateArea{
    public double calculateArea(IFeatureLayer featureLayer)throws IOException,
        AutomationException;
}

Defining a Java class that implements the custom interface

For ArcGIS to recognize this class as a Java extension, it needs to be decorated with the @ArcGISExtension annotation as shown in the following code snippet:
[Java]
@ArcGISExtension 
// Decorated with annotation.
public class CalcAreaUtil implements ICalculateArea{}

Implementing the custom interface

The utility object should now implement all of the custom interfaces it has defined.
The following snippet shows an implementation of the calculateArea” method declared on the ICalculateArea custom interface. 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;
}

Deploying 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 or 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 and class file dependencies, see Sun’s documentation on this subject. 
Once exported to a .jar file, the utility object needs to be deployed to ArcGIS so clients can use it. The two methods of deployment are as follows: 

Consuming a utility object

Once deployed, a utility object can be consumed from an Engine or Server application as shown in the following code snippets. The code snippets illustrate how to create an instance of a utility object and call the calculateArea method on it, passing in the second 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 (a fine-grained ArcObjects or a 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 licensingDeployment licensing
Engine Developer KitEngine
ServerServer