Introduction
The architecture for tasks provides a framework that allows for the implementation of custom tasks. In this section you will learn how to use the task framework to
In this section you will be writing a task that will parse a GeoRSS URL to display the data on the map. Below are the pre-requisites before you create a custom task.
After satisfying the above pre-requisites you should be able view an application in Eclipse similar to the screencapture shown below.
Implementing a Custom Task
Creating a custom task involves just three steps:
You will put the above steps into action by writing a task that takes an GeoRSS URL as an input parameter and add the locations on the map as web graphics.
Create a Java class
Create a new Java class GeoRSSTask inside a package called Demo. Right click on the src node select New -> Class. Type demo for the package name and GeorssTask for the name of the class.
You will add one parameter to get the URL for the GeoRSS feed, a command to add locations on the map, and a command to clear the locations on the map. Open the newly created Java class, GeorssTask by clicking it under the src node. Type the code as shown. The explanation of the methods used in the class are
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.setOutline("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;
}
}
Register managed-bean
You have completed writing the Java code for the task, now it's time to register the task as a managed-bean. Open the faces-config.xml file by navigating to WebContent -> WEB-INF. Scroll down to the end of the file and add the code below before the tag </faces-config>.
<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>
Add task control to jsp
The last step is to add the task control for georss task. Open the file mapviewer.jsp inside the WebContent node. Scroll to the end of the page and add the new task control along with other task already in the page. Add the code below after the </body> tag.
<a:task mapId="map1" id="addGeorssTask" value="#{addGeorssTask}" style="width:400px;height:100px;"/>
In the Web map application created by eclipse the tasks are represented as links that are activated by clicking on the link. First locate the code for the existing task links of the application in the JSP and add the link for the georss task. Your code should like below. The code you added is in bold and the code in italic was already in the application.
<!-- 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>
You have completed all the steps required to implement a custom task. Save all the files and run the application by right clicking on the file index.html and selecting Run As -> Run on Server . The application will deploy and open in a browser window inside the IDE. Click on the Tasks panel to open it and click on the Add Georss Layer link. Enter a GeoRSS URL in the input box. You can use one of the latest earthquakes feeds provided by USGS. To see earthquake locations for the past seven days with magnitude greater than 2.5 use the URL http://earthquake.usgs.gov/recenteqsww/catalogs/eqs7day-M2.5.xml. Click on the Add Georss Source button to add the earthquake locations as points on the map. After executing the task your output should look similar to the screencapture below. The earthquake locations themselves may be different in your application. Use the Clear Graphics button to remove the added locations.
Working with task results
The task just displays earthquake locations on the map. In this section you will add more 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 create a tool and a task results object to hold the attribute information. The results object will also have two action methods for highlighting and clearing the highlight of the selected location. Create a new Java class GeorssTaskResults and add the code below.
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.setOutline("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);
}
}
You have seen earlier in the Introduction section that the task results should contain a method to get the display name and an optional method to display the details of the results.
Now add a tool that would be used to drag a rectangle on the map and find the attribute information of the earthquake locations. A tool in a task should take MapEvent as an argument and the updated code for GeorssTask should look like below. The code in bold is the code you need to add in this step.
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.setOutline("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;
}
}
Let's see what you just added:
You have also learned from the introduction section that a tool in a task need to provide information about the client action to the task framework. You have already referenced the TaskInfo class GeorssTaskInfo in the code above. Now create the class GeorssTaskInfo. Add the code below to the created class.
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;
}
}
You have added the tool to the task, created a taskinfo class, and now you need to add the reference to the taskinfo class in the task control tag. Open mapviewer.jsp and modify the previously added task control to add the taskinfo reference. Your modified code should like below.
<a:task mapId="map1" id="addGeorssTask" value="#{addGeorssTask}" taskInfo="#{addGeorssTask.taskInfo}" style="width:350px;height:100px;"/>
Save all the files and run the application by right clicking on the file index.html and selecting Run As -> Run on Server. The application will deploy and open in a browser window inside the IDE. Click on the Tasks panel to open it and click on the Add Georss Layer link. You should see the inputs for the task in a window like below. Type in a GeoRSS URL as before and click on the button Add Georss Source to add the locations. Click on 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. Click on a result link to see the attribute information in the Results Details panel. Right click on 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 should appear like below.

Customizing task inputs
In the application you 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 need to be added to the taskinfo of the task. Modify the GeorssTaskInfo class with the code below
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;
}
}
Save all the files and run the application by right clicking on the file index.html and selecting Run As -> Run on Server . The application will deploy and open in a browser window inside the IDE. Click on the Tasks panel to open it and click on the Add Georss Layer link. You should see the inputs for the task in a window like below. All the functionalities should work as before.