How to write a custom task


Summary The tasks architecture provides a framework that allows the implementation of custom tasks. This topic shows how to use the task framework to implement a custom task, work with the results object, add action items (context menu) to task results, and customize the visualization of task inputs.

In this topic


Implementing a custom task

Implementing a custom task involves the following steps:
  1. Creating a Java class
  2. Registering the Java class as a managed bean in the faces-config.xml file
  3. Adding the task control to the JavaServer Pages (JSP) page, with reference to the managed bean
In this topic, you will write a task that takes a GeoRSS uniform resource locator (URL) as an input parameter and add locations on the map as Web graphics.

Creating a Java class

Create a new Java class called GeoRSSTask inside a package called demo.
  1. Right-click the src node in the georss file, click New, and click Class as shown in the following screen shot.
Create new class
The New Java Class dialog box opens as shown in the following screen shot.
Create new class
  1. Type demo for the package name, type GeorssTask for the name of the class, and click Finish.
You'll now use the following code to perform the following tasks.
  • Add a parameter to obtain the URL for the GeoRSS feed
  • Add a command to create locations on the map
  • Add a command to clear the locations on the map
  1. Open the newly created Java class, GeorssTask, by clicking it under the src node.
  2. Type the code as shown.
The explanation of the methods used in the class are as follows:
  • set/getGeorssURL—Interpreted as a parameter and is used to obtain the GeoRSS URL.
  • addGeorssSource—Interpreted as a command since the method takes TaskEvent as an argument. This method draws the coordinates as Web graphics on the map.
  • getGeorssCoords—A business function that parses the GeoRSS XML document and stores the information in a hash table.
  • clearGraphics—A command to clear all the locations on the map.
[Java]
package demo;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.esri.adf.web.data.WebGraphics;
import com.esri.adf.web.data.GraphicElement;
import com.esri.adf.web.data.geometry.WebGeometry;
import com.esri.adf.web.data.geometry.WebPoint;
import com.esri.adf.web.data.symbol.WebSimpleMarkerSymbol;
import com.esri.adf.web.faces.event.TaskEvent;
public class GeorssTask{
    private String georssURL = null;
    private Hashtable hash;

    public void setGeorssURL(String georssURL){
        this.georssURL = georssURL;
    }
    public String getGeorssURL(){
        return georssURL;
    }
    public void addGeorssSource(TaskEvent event){
        try{
            getGeorssCoords(getGeorssURL());
            if (hash.size() > 0){
                WebSimpleMarkerSymbol pSymbol = new WebSimpleMarkerSymbol();
                pSymbol.setColor("0,255,255");
                pSymbol.setMarkerType(4);
                pSymbol.setOutlineColor("0,0,0");
                pSymbol.setWidth(20);
                Enumeration locations = hash.keys();
                while (locations.hasMoreElements()){
                    String[] strLoc = locations.nextElement().toString().split(":");
                    if (strLoc.length >= 2){
                        WebPoint webPoint = new WebPoint();
                        webPoint.putCoords(Double.parseDouble(strLoc[0]),
                            Double.parseDouble(strLoc[1]));
                        if (webPoint != null){
                            WebGeometry webGeometry = 

                            (WebGeometry)webPoint;
                            GraphicElement graphicElem = 


                            new GraphicElement();
                            graphicElem.setGeometry(webGeometry);
                            graphicElem.setSymbol(pSymbol);
                            event.getWebContext().getWebGraphics().addGraphics
                                (graphicElem);
                        }
                    }
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
    public void clearGraphics(TaskEvent event){
        WebGraphics graphics = event.getWebContext().getWebGraphics();
        if (graphics ! = 


        null)
            graphics.clearGraphics();
    }
    public Hashtable getGeorssCoords(String urlPath){
        Document doc;
        try{
            DocumentBuilderFactory docBuilderFactory = 


            DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            URL url = new URL(urlPath);
            URLConnection urlConnection = 


            url.openConnection();
            urlConnection.connect();
            doc = docBuilder.parse(urlConnection.getInputStream());
            doc.normalize();
            NodeList listOfFeatures = 


            doc.getElementsByTagName("item");
            if (hash =  = null)
                hash = new Hashtable();
            for (int i = 0; i < listOfFeatures.getLength(); i++){
                Element featElem = (Element)listOfFeatures.item(i);
                String coord = new String(featElem.getElementsByTagName("geo:long")
                    .item(0).getFirstChild().getNodeValue() + ":" +
                    featElem.getElementsByTagName("geo:lat").item(0).getFirstChild()
                    .getNodeValue());
                Map map = new HashMap();
                for (int j = 0; j < featElem.getChildNodes().getLength(); j++){
                    NodeList pAttrList = featElem.getChildNodes();
                    Node attrNode = pAttrList.item(j);
                    if (attrNode.getNodeType() == 1){
                        map.put(attrNode.getNodeName().toString(),
                            attrNode.getFirstChild().getNodeValue());
                    }
                }
                hash.put(coord, map);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return hash;
    }
}

Registering a managed bean

When you have completed writing the Java code for the task, you need to register the task as a managed bean.
  1. Open the faces-config.xml file by navigating to WebContent, then to WEB-INF.
  2. Scroll down to the end of the file and add the following code before the tag </faces-config>.
[Java]
 < managed - bean >  < managed - bean - name > addGeorssTask <  / managed - bean -
     name >  < managed - bean - class > demo.GeorssTask <  / managed - bean - class
     >  < managed - bean - scope > session <  / managed - bean - scope >  <  /
     managed - bean >

Adding the task control to the JSP page

  1. Open the mapviewer.jsp file in the WebContent node.
  2. Scroll to the end of the page and add the new task control to the list of other tasks already on the page by adding the following code after the </body> tag.
[Java]
 < a: task mapId = "map1" id = "addGeorssTask" value = "#{addGeorssTask}" style = 
     "width:400px;height:100px;" /  >
In the Eclipse Web map application, tasks are represented as links that are activated by clicking the link.
  1. Locate the code for the existing task links of the application in the JSP and add the link for the georss task. Your code will look like the following code.
[Java]
 < !--Panel Content Divs-- >  < div id = "taskPanelContent" class = "content" >  <
     table border = "0" >  < tr >  < td >  < a href = "javascript:void(0);" onclick 
     = "toggleWindow('win_EsriTaskCell_searchAttributesTask');" > Search Attributes
     <  / a >  <  / td >  <  / tr >  < tr >  < td >  < a href = 
     "javascript:void(0);" onclick = 
     "toggleWindow('win_EsriTaskCell_addGeorssTask');" > Add Georss Layer <  / a > 
     <  / td >  <  / tr >  <  / table >  <  / div >
  1. Save your files.

Running the application

You have completed the steps to implement a custom task. To run the application, follow the steps outlined here.
  1. Right-click the index.html file, click Run As, and click Run on Server. The application deploys and opens in a browser window in the integrated development environment (IDE).
  2. Click the Tasks panel and click the Add Georss Layer link.
  3. Enter a GeoRSS URL in the input box.
For example, you can use one of the latest earthquake feeds provided by the U.S. Geological Survey (USGS). For earthquake locations in the past seven days with a magnitude greater than 2.5, use http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml.
  1. Click the Add Georss Source button to add the earthquake locations as points on the map.
After executing the task, your output will look similar to the following screen shot.
  1. Click the Clear Graphics button to remove the added locations.

Working with task results

Your application displays earthquake locations on the map. In this section you will add functionality to find attribute information about the locations. You will add a tool that will enable dragging a rectangle and selecting the locations to view their attribute information. You will also create a tool and a task results object to hold the attribute information. The results object will have two action methods: one for highlighting selected locations and one for clearing the highlight of the selected locations.

Adding functionality 

  1. Create a new Java class called GeorssTaskResults and add the following code.
[Java]
package demo;
import java.util.Map;
import com.esri.adf.web.data.GraphicElement;
import com.esri.adf.web.data.WebContext;
import com.esri.adf.web.data.WebGraphics;
import com.esri.adf.web.data.geometry.WebGeometry;
import com.esri.adf.web.data.symbol.WebSimpleMarkerSymbol;
public class GeorssTaskResults{
    protected String rssName = null;
    protected Map rssDetails = null;
    protected WebGeometry highlightGeometry;
    protected WebContext webcontext = null;
    protected GraphicElement graphicElem;
    public GeorssTaskResults(WebContext webcontext, WebGeometry highlightGeometry){
        this.webcontext = webcontext;
        if (highlightGeometry != null)
            this.highlightGeometry = webcontext.project(highlightGeometry);

        graphicElem = new GraphicElement();
        graphicElem.setGeometry(highlightGeometry);
    }
    public String getRssName(){
        return rssName;
    }
    public void setRssName(String rssName){
        this.rssName = rssName;
    }
    public Map getRssDetails(){
        return rssDetails;
    }
    public void setRssDetails(Map rssDetails){
        this.rssDetails = rssDetails;
    }
    public void highlight(){
        WebSimpleMarkerSymbol pSymbol = new WebSimpleMarkerSymbol();
        pSymbol.setColor("255,255,0");
        pSymbol.setMarkerType(4);
        pSymbol.setOutlineColor("0,0,0");
        pSymbol.setWidth(20);
        graphicElem.setSymbol(pSymbol);

        WebGraphics graphics = webcontext.getWebGraphics();
        graphics.addGraphics(graphicElem);
    }
    public void clearHighlight(){
        WebGraphics graphics = webcontext.getWebGraphics();
        graphics.removeGraphics(graphicElem);
    }
}
The methods you'll use in this section are as follows:
  • set/getRssName—Obtains the display name
  • set/getRssDetails—Obtains the details of the result
  • highlight—An action method that highlights the location
  • clearHighlight—An action method that clears the highlight for a specific location
Now you'll add a tool to drag a rectangle on the map and find the attribute information of the earthquake locations. A tool in a task takes MapEvent as an argument, and the updated code for GeorssTask will look like the following code.
  1. Add the code that's set off in double quotes ("").
[Java]
package demo;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.esri.adf.web.data.WebGraphics;
import com.esri.adf.web.data.GraphicElement;
import com.esri.adf.web.data.geometry.WebGeometry;
import com.esri.adf.web.data.geometry.WebPoint;
import com.esri.adf.web.data.symbol.WebSimpleMarkerSymbol;
import com.esri.adf.web.faces.event.TaskEvent;

""import com.esri.adf.web.data.tasks.SimpleTaskInfo;
import com.esri.adf.web.data.geometry.WebExtent;
import com.esri.adf.web.faces.event.MapEvent;
import java.util.ArrayList;
import java.util.LinkedHashMap;
""


public class GeorssTask{
    private String georssURL = null;
    private Hashtable hash;
    "" private GeorssTaskInfo taskInfo = new GeorssTaskInfo();
    ""

    public void setGeorssURL(String georssURL){
        this.georssURL = georssURL;
    }
    public String getGeorssURL(){
        return georssURL;
    }
    public void addGeorssSource(TaskEvent event){
        try{
            getGeorssCoords(getGeorssURL());
            if (hash.size() > 0){
                WebSimpleMarkerSymbol pSymbol = new WebSimpleMarkerSymbol();
                pSymbol.setColor("0,255,255");
                pSymbol.setMarkerType(4);
                pSymbol.setOutlineColor("0,0,0");
                pSymbol.setWidth(20);
                Enumeration locations = hash.keys();
                while (locations.hasMoreElements()){
                    String[] strLoc = locations.nextElement().toString().split(":");
                    if (strLoc.length >= 2){
                        WebPoint webPoint = new WebPoint();
                        webPoint.putCoords(Double.parseDouble(strLoc[0]),
                            Double.parseDouble(strLoc[1]));
                        if (webPoint != null){
                            WebGeometry webGeometry = (WebGeometry)webPoint;
                            GraphicElement graphicElem = 


                            new GraphicElement();
                            graphicElem.setGeometry(webGeometry);
                            graphicElem.setSymbol(pSymbol);
                            event.getWebContext().getWebGraphics().addGraphics
                                (graphicElem);
                        }
                    }
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
    public void clearGraphics(TaskEvent event){
        WebGraphics graphics = 


        event.getWebContext().getWebGraphics();
        if (graphics ! = null)
            graphics.clearGraphics();
    }
    public Hashtable getGeorssCoords(String urlPath){
        Document doc;
        try{
            DocumentBuilderFactory docBuilderFactory = 

            DocumentBuilderFactory .newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            URL url = new URL(urlPath);
            URLConnection urlConnection = 

            url.openConnection();
            urlConnection.connect();
            doc = docBuilder.parse(urlConnection.getInputStream());
            doc.normalize();
            NodeList listOfFeatures = 


            doc.getElementsByTagName("item");
            if (hash = 

             = null)
                hash = new Hashtable();
            for (int i = 0; i < listOfFeatures.getLength(); i++){
                Element featElem = (Element)listOfFeatures.item(i);
                String coord = new String(featElem.getElementsByTagName("geo:long")
                    .item(0).getFirstChild().getNodeValue() + ":" +
                    featElem.getElementsByTagName("geo:lat").item(0).getFirstChild()
                    .getNodeValue());
                Map map = 


                new HashMap();
                for (int j = 0; j < featElem.getChildNodes().getLength(); j++){
                    NodeList pAttrList = featElem.getChildNodes();
                    Node attrNode = pAttrList.item(j);
                    if (attrNode.getNodeType() == 1){
                        map.put(attrNode.getNodeName().toString(), attrNode
                            .getFirstChild().getNodeValue());
                    }
                }
                hash.put(coord, map);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return hash;
    }


    "" public void search(MapEvent event){
        WebExtent ext = (WebExtent)event.getWebGeometry().toMapGeometry
            (event.getWebContext().getWebMap());
        Enumeration locations = hash.keys();
        ArrayList results = null;
        GeorssTaskResults geoRss = null;
        Map rssInfo = null;
        while (locations.hasMoreElements()){
            String loc = locations.nextElement().toString();
            WebPoint webpoint = new WebPoint(Double .parseDouble(loc.split(":")[0]),
                Double.parseDouble(loc .split(":")[1]));
            if (ext.contains(webpoint)){
                rssInfo = (Map)hash.get(loc);
                if (results == null)
                    results = new ArrayList();
                geoRss = new GeorssTaskResults(event.getWebContext(), webpoint);
                geoRss.setRssName(rssInfo.get("title").toString());
                geoRss.setRssDetails(rssInfo);
                results.add(geoRss);
            }
        }
        Map actions = new LinkedHashMap();
        actions.put("Highlight", "highlight");
        actions.put("Clear Highlight", "clearHighlight");
        if (results != null)
            event.getWebContext().getWebResults().addResultsWithActionMap(
                "GeoRSS Search Results : ", results, "getRssName", "getRssDetails",
                actions);
    }

    public SimpleTaskInfo getTaskInfo(){
        return this.taskInfo;
    }
    ""

}
You added the following tool and method: 
  • search—A tool that takes MapEvent as an argument. The tool selects all the earthquake locations in the user-drawn rectangle and adds them to the results collection.
  • getTaskInfo—A utility method that obtains the task info.
A tool in a task must provide information about the client action to the task framework. You have already referenced the TaskInfo class, GeorssTaskInfo, in the previous code sample. Now you'll create the class GeorssTaskInfo.
  1. Add the following code to the created class.
[Java]
package demo;
import com.esri.adf.web.data.tasks.SimpleTaskInfo;
import com.esri.adf.web.data.tasks.TaskToolDescriptor;
import com.esri.adf.web.data.tasks.TaskToolDescriptorModel;
import com.esri.adf.web.faces.event.ClientActions;
public class GeorssTaskInfo extends SimpleTaskInfo{
    private TaskToolDescriptor[] toolDescs = new TaskToolDescriptor[1];
    public GeorssTaskInfo(){
        toolDescs[0] = new TaskToolDescriptor(GeorssTask.class, "search", "Search",
            ClientActions.MAP_RECTANGLE);
    }

    public TaskToolDescriptorModel[] getToolDescriptors(){
        return toolDescs;
    }
}
Now you need to add the reference to the taskinfo class in the task control tag.
  1. Open mapviewer.jsp and modify the previously added task control to add the taskinfo reference. Your modified code should look like the following code.
[Java]
 < a: task mapId = "map1" id = "addGeorssTask" value = "#{addGeorssTask}" taskInfo =
     "#{addGeorssTask.taskInfo}" style = "width:350px;height:100px;" /  >
  1. Save your files.

Running the application

You have completed the steps to add functionality. To run the application, follow the steps outlined here.
  1. Right-click the index.html file, click Run As, and click Run on Server. The application deploys and opens in a browser window in the IDE.
  2. Click the Tasks panel and click the Add Georss Layer link.
  3. Enter a GeoRSS URL in the input box.
For example, you can use one of the latest earthquake feeds provided by U.S. Geological Survey (USGS). For earthquake locations in the past seven days with a magnitude greater than 2.5, use http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml.
  1. Click the Add Georss Source button to add the earthquake locations as points on the map.
  2. Click the Search button and drag a rectangle on the map to find the attribute information of the locations. The results will appear in the Results panel on the left.
  3. Click a result link to see the attribute information in the Results Details panel.
  4. Right-click the results to activate the context menu, select highlight to highlight the location of that result, and select clear highlight to clear the highlight for that result.
The completed application with the commands, tool, and the results will be similar to the following screen shot.

Customizing task inputs

In the application you just created, the commands and tools are represented as HTML buttons and are placed using the default layout rendered by the task framework. You can customize the rendering style of the commands and tools to use images. These customization parameters must be added to the taskinfo of the task.

Modifying the GeorssTaskInfo class

  1. Modify the GeorssTaskInfo class with the following code.
[Java]
package demo;
import com.esri.adf.web.data.tasks.SimpleTaskInfo;
import com.esri.adf.web.data.tasks.TaskToolDescriptor;
import com.esri.adf.web.data.tasks.TaskToolDescriptorModel;
import com.esri.adf.web.faces.event.ClientActions;
import com.esri.adf.web.data.tasks.TaskActionDescriptor;
import com.esri.adf.web.data.tasks.TaskActionDescriptorModel;
import com.esri.adf.web.data.tasks.TaskDescriptor;
import com.esri.adf.web.data.tasks.TaskLayout;
import com.esri.adf.web.data.tasks.TaskParamDescriptor;
import com.esri.adf.web.data.tasks.TaskParamDescriptorModel;

public class GeorssTaskInfo extends SimpleTaskInfo{
    private TaskDescriptor taskDesc = null;
    private TaskActionDescriptor[] taskActions = new TaskActionDescriptor[2];
    private TaskParamDescriptor[] taskParams = new TaskParamDescriptor[1];
    private TaskToolDescriptor[] taskTools = new TaskToolDescriptor[1];
    public GeorssTaskInfo(){
        taskDesc = new TaskDescriptor(GeorssTask.class, "GeoRSS", "GeoRSS Overlay");
        taskParams[0] = new TaskParamDescriptor(GeorssTask.class, "georssURL", 
            "Enter GeoRSS URL");
        taskTools[0] = new TaskToolDescriptor(GeorssTask.class, "search", "Search",
            ClientActions.MAP_RECTANGLE);
        taskTools[0].setDefaultImage("images/tasks/search/searchextent.gif");
        taskTools[0].setSelectedImage("images/tasks/search/searchextentD.gif");
        taskTools[0].setHoverImage("images/tasks/search/searchextentU.gif");
        taskTools[0].setDisabledImage("images/tasks/search/searchextent.gif");
        taskTools[0].setToolTip("Search by extent");
        taskTools[0].setRendererType(TaskToolDescriptor.IMAGE_RENDERER_TYPE);
        taskActions[0] = new TaskActionDescriptor(GeorssTask.class, 
            "addGeorssSource", "Add GeoRSS");
        taskActions[0].setToolTip("Add GeoRSS");
        taskActions[0].setDefaultImage("images/tasks/geoprocessing/gpAdd.gif");
        taskActions[0].setSelectedImage("images/tasks/geoprocessing/gpAddD.gif");
        taskActions[0].setHoverImage("images/tasks/geoprocessing/gpAddU.gif");
        taskActions[0].setDisabledImage("images/tasks/geoprocessing/gpAdd.gif");
        taskActions[0].setRendererType(TaskToolDescriptor.IMAGE_RENDERER_TYPE);
        taskActions[1] = new TaskActionDescriptor(GeorssTask.class, "clearGraphics",
            "Clear Locations");
        taskActions[1].setToolTip("Clear Graphics");
        taskActions[1].setDefaultImage("images/tasks/search/cleargraphics.gif");
        taskActions[1].setSelectedImage("images/tasks/search/cleargraphicsD.gif");
        taskActions[1].setHoverImage("images/tasks/search/cleargraphicsU.gif");
        taskActions[1].setDisabledImage("images/tasks/search/cleargraphics.gif");
        taskActions[1].setRendererType(TaskToolDescriptor.IMAGE_RENDERER_TYPE);

    }
    public TaskLayout[] getTaskLayout(){
        return null;
    }
    public TaskDescriptor getTaskDescriptor(){
        return taskDesc;
    }
    public TaskParamDescriptorModel[] getParamDescriptors(){
        return taskParams;
    }
    public TaskActionDescriptorModel[] getActionDescriptors(){
        return taskActions;
    }
    public TaskToolDescriptorModel[] getToolDescriptors(){
        return taskTools;
    }
}
  1. Save your files.

Running the application

  1. Right-click the index.html file, click Run As, and click Run on Server. The application deploys and opens in a browser window in the IDE.
  2. Click the Tasks panel and click the Add Georss Layer link.
  3. The inputs for the task appear in a window as shown in the following screen shot.
Task input
All the functionalities continue to operate as previously described.


See Also:

Eclipse IDE - ArcGIS Web Project Guide
Writing an advanced custom task




Additional Requirements
  • Access to a geographic information system (GIS) service supported by the Web Application Developer Framework (ADF). You can use the world.mxd file at [Web ADF install directory] \ArcGIS\java\samples\data\mxds to create either an ArcGIS Server service or an ArcIMS Service.
  • Eclipse IDE with the ArcGIS Server plug-in. In Eclipse, click File, click New, and click Project. Select ArcGIS Web Project under ESRI Templates and create a new Web application called georss.