Custom commands and tools


Summary The ArcGIS Web Application Developer Framework (ADF) contains a great deal of geospatial functionality. However, you can add your own geospatial functionality through custom commands, tools, and tasks.

This topic discusses how to add custom commands and tools by creating a class, adding business logic and methods to it, declaring the class a managed bean, and initializing the class with a reference to the WebContext. You can then add the command and the tool to a toolbar in a JavaServer Pages (JSP) page and set up their attributes to point to appropriate methods in the class.

In this topic


Commands

A command calls a server-side method without requiring further client interaction. A command is represented by a command JSP tag. The look of a command can be customized using the following attributes:
  • style
  • styleClass
  • defaultImage
  • selectedImage
  • hoverImage
  • disabledImage
  • toolTip
  • toolText
The server-side method to call can be specified using either the action or actionListener attributes. The action attribute must be a method binding to a Java method that accepts no arguments and has a return type of string. This method can be used to execute some business logic and to control page navigation. The actionListener attribute must be a method binding to a Java method that accepts an argument of type javax.faces.event.ActionEvent. This method can be used to execute some business logic but does not have any affect on page navigation. You can also specify the action listener by using a nested JavaServer Faces (JSF) actionListener tag with the type attribute pointing to a fully-qualified Java class that implements the javax.faces.event.ActionListener interface.
The Web ADF provides the following standard commands:
  • Zoom to full extent
  • Zoom to previous extent
  • Zoom to next extent
  • Directional pan

Tools

A tool requires some client interaction with the map before calling a server-side method. A tool is represented by a tool JSP tag. The look of a tool can be customized using the following attributes:
  • style
  • styleClass
  • defaultImage
  • selectedImage
  • hoverImage
  • disabledImage
  • toolTip
  • toolText
The clientAction attribute specifies the client-side script to execute. Elements of the client-side script can be customized using the cursor, lineWidth, and lineColor attributes. The clientAction attribute can take on the following values:
  • EsriMapCircle
  • EsriMapContinuousPan
  • EsriMapLine
  • EsriMapOval
  • EsriMapPan
  • EsriMapPoint
  • EsriMapPolygon
  • EsriMapPolyline
  • EsriMapRectangle
The server-side method to call can be specified using either the serverAction or serverMethod attributes. The serverAction attribute must be a fully qualified name of a Java class implementing the com.esri.web.adf.faces.event.MapToolAction interface. The serverMethod attribute must be a method binding to a Java method that accepts an argument of type com.esri.adf.web.faces.event.MapEvent. The server-side method can be called asynchronously or synchronously using the clientPostBack attribute.
The Web ADF provides the following standard tools:
  • Zoom in
  • Zoom out
  • Pan

Writing a custom command and tool

The custom command will count all visible features in a layer. The custom tool will count only those features that are within a rectangle drawn on the map. For this discussion, assume you have a Web ADF application working against an ArcGIS Map Service.

Implementing the Java class

Create a class called FeatureCounter that implements the logic of counting features. This class will use the ArcGIS Server application programming interface (API) to count features, so it will need a reference to the WebContext to get to this API. Add a property called context to hold this reference and add getter/setter methods for it. You'll initialize this property later. Add a property called countedFeatures to hold the number of features and add getter/setter methods. The following code sample shows how the class will initially look.
[Java]
package com.mypackage;
public class FeatureCounter{
    private WebContext context;
    public WebContext getWebContext(){
        return context;
    }
    public void setWebContext(WebContext context){
        this.context = context;
    }
    private int countedFeatures;
    public int getCountedFeatures(){
        return countedFeatures
    };
    public void setCountedFeatures(int count){
        this.countedFeatures = count;
    }
}
Add a private method called countFeatures() that takes in an argument of type com.esri.adf.web.data.WebContext. This method will do the actual counting of all the features in an extent and store the result in the property countedFeatures. This is shown in the following code sample.
[Java]
private void countFeatures(WebExtent extent){
    //Get the MapServerPort to execute methods through the ArcGIS Server API.
    AGSMapResource agsMap = ((AGSMapResource)context.getResources().get("ags1"));
    MapServerPort mapServer = agsMap.getMapServer();
    //Make a new envelope from the Web extent.
    EnvelopeN env = new EnvelopeN(extent.getMinX(), extent.getMinY(), extent.getMaxX
        (), extent.getMaxY(), null, null, null, null, null);
    //Set up a spatial filter for an intersection relationship.
    SpatialFilter spatialFilter = new SpatialFilter();
    spatialFilter.setSpatialRel(EsriSpatialRelEnum.esriSpatialRelIntersects);
    spatialFilter.setWhereClause("");
    spatialFilter.setSearchOrder(EsriSearchOrder.esriSearchOrderSpatial);
    spatialFilter.setSpatialRelDescription("");
    spatialFilter.setGeometryFieldName("");
    //Set the envelope as the geometry.
    spatialFilter.setFilterGeometry(env);
    //MapServer::queryFeatureCount() executes on the server and can throw a RemoteException.
    try{
        //Count features in the fourth layer that intersect with the envelope.
        int layerId = 3;
        this.countedFeatures = mapServer.queryFeatureCount
            (mapServer.getDefaultMapName(), layerId, spatialFilter);
    }
    catch (RemoteException rme){
        //Rethrow this as ADFAGSException so that it can participate in the exception framework.
        throw new ADFAGSException("Could not execute MapServer::queryFeatureCount()",
            rme);
    }
}
With the business logic ready, you need to add methods that will be called by the command and the tool. Create a command method called countFeaturesInFullExtent() that accepts no arguments and invokes countFeatures() with a WebExtent argument representing the full extent. This is shown in the following code sample.
[Java]
public String countFeaturesInFullExtent(){
    //Get the full extent.
    WebExtent fullExtent = context.getWebMap().getFullExtent()
    //Delegate to countFeatures().
    this.countFeatures(fullExtent);
    //Don't navigate to another page.
    return null;
}
Create a tool method called countFeaturesInRectangle() that accepts an argument of type com.esri.adf.web.faces.event.MapEvent and invokes countFeatures with a WebExtent argument representing the extent chosen by the user. This is shown in the following code sample.
[Java]
public int countFeaturesInRectange(MapEvent event){
    //Get the chosen extent.
    WebMap webMap = context.getWebMap();
    WebExtent chosenExent = (WebExtent)event.getWebGeometry().toMapGeometry(webMap);
    //Delegate to countFeatures().
    this.countFeatures(chosenExent);
    //Don't navigate to another page.
    return null;
}

Declaring the Java class as a managed bean

Declare FeatureCounter as a managed bean in WEB-INF/faces-config.xml and initialize it with an instance of WebContext. This is shown in the following code sample.
[Java]
 < managed - bean >  < managed - bean - name > featureCounter <  / managed - bean -
     name >  < managed - bean - class > com.mypackage.FeatureCounter <  / managed -
     bean - class >  < managed - bean - scope > request <  / managed - bean - scope
     >  < managed - property >  < property - name > webContext <  / property - name
     >  < value > #{
    mapContext
}

 <  / value >  <  / managed - property >  <  / managed - bean >

Adding the command and tool to the JSP page

You need to add the command and tool to a toolbar in the JSP page. The tool tag should specify EsriMapRectangle as the clientAction attribute. This allows the user to draw a rectangle on the map that is passed as a MapEvent argument to the method specified by the serverMethod attribute. The following code sample shows how your JSP page should look.
[Java]
 < a: toolbar id = "Toolbar" mapId = "Map0" ... > ... < a: tool id = 
     "countFeatures1" clientAction = "EsriMapRectangle" serverMethod = 
     "#{featureCounter.countFeaturesInRectangle}" toolText = 
     "Count Features in Extent" /  >  < a: command id = "countFeatures2" action = 
     "#{featureCounter.countFeaturesInFullExtent}" toolText = "Count All Features" /
     > ... <  / a: toolbar > .... Feature Count =  < h: outputText value = 
     "#{featureCounter.countedFeatures}" rendered = 
     "#{featureCounter.countedFeatures > 0}" /  >


See Also:

How to add a command or tool
Writing a custom task
Writing an advanced custom task