AJAX integration and support


Summary The term “AJAX” was introduced by Jesse James Garrett. It stands for Asynchronous JavaScript and XML and describes a Web programming model that allows content on a browser page to be updated without full postback to the Web server and the re-rendering of elements on the page.

This topic covers the integrated AJAX framework architecture in the Java Web Application Development Framework (ADF). This includes the core Java classes supporting AJAX, the client side JavaScript library, and the framework for adding custom AJAX renderers. Specific use cases are used to describe how a certain piece works in detail.

This topic assumes you have knowledge and some experience in developing Web applications using Java, JavaServer Faces (JSF), JavaScript, Extensible Markup Language (XML), and AJAX.

In this topic


ArcGIS Server and AJAX

ArcGIS Server at 9.3 is a complete Web-based geographic information system (GIS) developer platform for building server applications that can be consumed by a variety of clients. ArcGIS Server provides a rich ADF for the Java 5 Enterprise Edition (JavaEE) environment and a set of software components based on the JSF standard. This framework, called the Java Web ADF, is a platform for developing centrally managed JavaEE-based GIS applications. Along with JSF, the ADF incorporates and extends the AJAX programming model.

Java Web ADF lifecycle

When you add a map tag (com.esri.adf.web.faces.taglib.MapTag) to your JavaServer Pages (JSP) page, it is backed by the com.esri.adf.web.faces.component.MapControl JSF component. The map control is value bound to com.esri.adf.web.data.WebMap. WebMap is part of com.esri.adf.web.data.WebContext, which maintains reference to all the GIS resources and GIS business objects that are part of the executing application. As part of the response in the request-response lifecycle, the map control generates XML markup through com.esri.adf.web.faces.renderkit.xml.MapRenderer to represent the state of the map onto the page. The XML is transformed into Hypertext Markup Language (HTML) and a set of JavaScript objects using Extensible Style Language (XSL). The map control uses the WEB-INF/classes/xsl/map.xsl that includes the js/esri_map.js file and creates the EsriMap JavaScript object.
The following diagram shows how a map control evolves from a tag to an object on the browser page.
To support the server side controls and allow the development and customization of applications on the Web, the Java Web ADF provides an extensive JavaScript library. This collection of objects includes the EsriMap object. The JavaScript objects are initialized as part of the onload event of the HTML page. The JavaScript objects manipulate the HTML Document Object Model (DOM) and render the controls onto the page. In the case of the map, the GIS resources are added to the EsriMap object as EsriMapSourceDynamic and EsriMapSourceTile JavaScript objects.
The JavaScript library also provides a range of behaviors and actions (EsriAction) that can be used on the map. For example, EsriMapRectangle allows you to draw a rectangle on the map control. When you draw the rectangle to trigger a zoom-in operation, the screen coordinates of this rectangle are sent to the server. The JSF key-value pair of mapid=mapid lets the controls know that the map control is responsible for processing this operation. The mapid_mode=id identifies the specific operation to be performed on the map and the appropriate server side tool item is executed, then it returns to the request-response cycle.

JSF lifecycle

The JSF lifecycle consists of six phases as follows:
  1. Restore View
  2. Apply Request Values
  3. Process Validation
  4. Update Model Values
  5. Invoke Application
  6. Render Response
The JSF implementation processes the components on the form and renders the response back to the browser based on these phases. The Restore View and Render Response phases are considered system-level phases, and the others are considered application-level phases. All application-level phases can skip to the Render Response phase by calling javax.faces.context.FacesContext.renderResponse().
The following diagram shows the JSF lifecycle.
 
The purpose of the Apply Request Values phase is for each component to retrieve its current state. Component values are typically retrieved from the request parameters. Any updated values you set by interacting with the application in the browser are passed to the appropriate components during this phase.
Another method that is used in the client side postback implementation is javax.faces.component.UICommand.setImmediate(). This method sets a flag on UICommand to process immediately without waiting for the Invoke Application phase. The javax.faces.context.FacesContext.responseComplete() method signals the JSF implementation that the response rendering is complete and the JSF request processing lifecycle should terminate as soon as the current phase is completed.
Any class that implements the javax.faces.event.PhaseListener interface and is registered in the lifecycle of the JSF application will be notified at the beginning and ending of processing for the phase whose ID is returned by the PhaseListener.getPhaseId() method.

AJAX lifecycle

The AJAX lifecycle is independent of the implementation on the server. This means that the browser sends a request with certain parameters and expects an XML response in a specific format. The response can be generated from any type of JSF PhaseListener, servlet, or static XML file.
The following diagram shows the AJAX lifecycle.
 
When the browser uses the XMLHttpRequest object to send a request to the server, the request follows the standard JSF request processing lifecycle. The components have been restored in the Restore View phase and their state has been updated in the Apply Request Values phase. Since the components on the page must be updated, you can skip processing in the PhaseListener.beforePhase() method. Instead, use the PhaseListener.afterPhase() method to process the request and render the response to the client.
The request parameter should contain all the information required by the PhaseListener. For example, the ID of the form within which the component to be updated exists and the ID of the component to be updated. The components are accessible in javax.faces.component.UIViewRoot as defined on the page. The JSF components can be accessed as children to other javax.faces.component.UIComponents through the UIComponent.findComponent() method. You need to know the hierarchy of the components as shown on the JSP page to access the correct component. For this reason, you should assign IDs to all components that require updating through AJAX and other DOM manipulation on the browser.
For example, if the request parameters contain the form and map IDs, javax.faces.component.html.HtmlForm can be obtained as a child of UIViewRoot and the MapControl as a child of the HtmlForm component. Once you understand the MapControl, you can access the WebMap, which is the GIS business object behind the MapControl. You can use the WebMap for further processing from this point.
Once the processing is complete, the XML response must be returned to the client. The com.esri.adf.web.util.XMLUtil class provides several utility methods that can be used to create and populate an XML document. It is recommended that you render all XML elements within one root element. The Java Web ADF renders all AJAX responses within a <response> element. The com.esri.adf.web.faces.renderkit.xml.ajax.AJAXUtil.writeResponse() method is the preferred method for rendering the XML response back to the client. Once the response XML has been written to the output stream, it is required to call FacesContext.responseComplete() to inform the JSF implementation that the response has been written. If it’s not written, the JSF lifecycle continues through the phases until either FacesContext.responseComplete() is called or the RenderResponse phase renders the response.
Once the response is returned to the browser, the XMLHttpRequest object handles calling the appropriate callback function for processing the response and passes itself as reference. The callback function should use the XMLHttpRequest.responseXML to get to the XML document. At this point, the XML document can be traversed using standard DOM functions in JavaScript, and the HTML elements in the browser page are updated.

Use case 1: Map Information application

This use case shows how to accomplish the following tasks:
  • Send a request to the server using XMLHttpRequest
  • Use a PhaseListener to process the request and render an XML response
  • Parse the XML response to update elements on the browser page using JavaScript
The Map Information application allows you to update content on the browser page based on the change in the current extent of the map. When running this application and zooming in and out or panning the map, a request is sent to the server and the extent and scale of the map is retrieved and displayed.
The following screen shot is of the Map Information application.

mapInformation.jsp

The mapInformation.jsp page contains a map control and a table with several placeholders to display the extent and scale of the currently visible map as shown in the following code sample.
The call to the init() JavaScript function initializes some behavior in the application.
[XML]
<body onload="init()"><a:map id="map" value="#{mapContext.webMap}"/>
  …
  Map Information :
  <table><tbody>
    <tr>
      <td>MinX : </td><td><span id="minx"></span></td>
    </tr><tr>
      <td>MinY : </td><td><span id="miny"></span></td>
    </tr><tr>
      <td>MaxX : </td><td><span id="maxx"></span></td>
    </tr><tr>
      <td>MaxY : </td><td><span id="maxy"></span></td>
    </tr><tr>
      <td>Scale : </td><td><span id="map-scale"></span></td>
    </tr>
  </tbody></table></body>

mapInformation.js

The mapInformation.js file defines a set of JavaScript functions used in this application. The init() function sets up a listener to the map control to be notified whenever the map is updated as shown in the following code sample.
[Java]
map.addUpdateListener("mapInformationListener", updateMapInformationRequest);
The updateMapInformationRequest() function allows you to send requests to the server to obtain the required map information. Before sending the request to the server, however, you need to set up parameters for the request. First, you need to get the uniform resource locator (URL) of the server to which you are sending the request as shown in the following code sample.
[Java]
var url = adf.Utils.getServerUrl(map.formId);
Build the request parameters that are to be sent to the server for processing the request. As part of the list of parameters, include the parameters from form elements in which the map is rendered as shown in the following code sample.
[Java]
var params = "mapinformation=mapinformation&formId=" + map.formId + "&mapId=" +
    map.id + "&" + adf.Utils.buildRequestParams(map.formId);
Send the request to the server. In addition to passing the server URL, the parameters string, and either the POST or GET function, pass the callback function, which must be called when the XMLHttpRequest object is updated as shown in the following code sample.
[Java]
var xmlHttp = adf.Utils.sendAjaxRequest(url, params, true,
    updateMapInformationResponse)
The parameters that are sent to the server for processing are as follows:
  • Mapinformation—Helps the appropriate phase listener identify whether it's responsible for processing the request
  • map.formId—Helps the phase listener identify the form in which the map control is rendered
  • map.id—Helps the phase listener obtain the map control from the form

MapInformationPhaseListener.java

MapInformationPhaseListener is the class that processes the request and gets the map control and its current extent and scale information. It then renders this information as XML and returns a response to the client.
The MapInformationPhaseListener class implements the methods defined in the PhaseListener interface. PhaseListener.getPhaseId() tells the JSF implementation about the phase during which this PhaseListener is to be notified as shown in the following code sample.
[Java]
public PhaseId getPhaseId(){
    return PhaseId.APPLY_REQUEST_VALUES;
}
The Apply Request Values phase is the phase where every control retrieves updated values from the request parameter.
The PhaseListener.beforePhase() method is not used because the values of the controls must be updated before performing any updates as shown in the following code sample.
[Java]
public void beforePhase(PhaseEvent phaseEvent){
    //Do nothing.
}
The PhaseListener.afterPhase() method processes the request as shown in the following code sample.
[Java]
public void afterPhase(PhaseEvent phaseEvent){
    // Determine if this PhaseListener is responsible for 
    // processing the request.
    // Process the request.
    // Render and return a response.
}
Determine if the request is to be processed by this PhaseListener. This can be done by checking if a specific parameter is present in the request. For example, with MapInformationPhaseListener, check whether the request parameter mapinformation is equivalent to “mapinformation” as shown in the following code sample.
[Java]
FacesContext facesContext = phaseEvent.getFacesContext();
ExternalContext externalContext = facesContext.getExternalContext();
Map params = externalContext.getRequestParameterMap();
if (!"mapinformation" .equals(params.get("mapinformation")))
    return ;
The facesContext object refers to the FacesContext instance, of which this PhaseListener is a part. Thus, it has access to all the components that are rendered in the view root of the page. Use the request parameters to find the components of interest for your processing. For example, you can find the form and map control on the page as shown in the following code sample.
[Java]
String formId = (String)params.get("formId");
UIComponent form = facesContext.getViewRoot().findComponent(formId);
String mapId = (String)params.get("mapId");
MapControl mapControl = (MapControl)form.findComponent(mapId);
WebMap map = mapControl.getWebMap();
Perform the necessary processing with the desired component and GIS business object as shown in the following code sample.
[Java]
WebExtent extent = map.getCurrentExtent();
double scale = map.getMapScale();
As part of the AJAX response, an XML response must be sent back to the client. Create the XML document and populate it as shown in the following code sample.
[XML]

Document doc = XMLUtil.newDocument();
Element responseElement = XMLUtil.createElement(doc, "response", null, null);
XMLUtil.createElement("minx", Double.toString(extent.getMinX()), responseElement);
XMLUtil.createElement("miny", Double.toString(extent.getMinY()), responseElement);
XMLUtil.createElement("maxx", Double.toString(extent.getMaxX()), responseElement);
XMLUtil.createElement("maxy", Double.toString(extent.getMaxY()), responseElement);
XMLUtil.createElement("map-scale", Double.toString(scale), responseElement);
Once the XML response document has been created and populated with the required information, write it back to the client using AJAXUtil.writeResponse() as shown in the following code sample.
[Java]
AJAXUtil.writeResponse(facesContext, doc);
When the processing of the request and the response is complete, notify the JSF implementation that the rendering of the response is complete so that the JSF lifecycle terminates at the end of this phase as shown in the following code sample.
[Java]
facesContext.responseComplete();
The MapInformationPhaseListener class has completed its work. To register a phase listener in the JSF lifecycle, it must be included in faces-config.xml as shown in the following code sample.
[Java]
 < lifecycle >  < phase - listener >
     com.esri.arcgis.sample.mapinformation.MapInformationPhaseListener <  / phase -
     listener >  <  / lifecycle >
The response is returned to the updateMapInformationResponse JavaScript function. This function is now responsible for parsing the XML and updating the appropriate HTML elements on the page as shown in the following code sample.
[XML]

var xml = xmlHttp.responseXML;
document.getElementById("minx").innerHTML = xml.getElementsByTagName("minx").item(0).firstChild.nodeValue;
document.getElementById("miny").innerHTML = xml.getElementsByTagName("miny").item(0).firstChild.nodeValue;
document.getElementById("maxx").innerHTML = xml.getElementsByTagName("maxx").item(0).firstChild.nodeValue;
document.getElementById("maxy").innerHTML = xml.getElementsByTagName("maxy").item(0).firstChild.nodeValue;
document.getElementById("map-scale").innerHTML = xml.getElementsByTagName("mapscale").item(0).firstChild.nodeValue;
Use case 1 is now complete.

Postback lifecycle

AJAX is now integrated into your Java Web ADF application. The Java Web ADF contains several PhaseListeners that are used to process AJAX requests. The most important one is com.esri.adf.web.faces.event.PostBackPhaseListener, which enables AJAX support for all the Web ADF controls.
The following diagram shows the JSF lifecycle with postback.
The PostBackPhaseListener listens to phase events in the Apply Request Phase. In the beforePhase() method, this class identifies the UICommand that triggered the request and sets its immediate flag to true. It then creates a new instance of the com.esri.adf.web.faces.renderkit.xml.ajax.AJAXResponseRenderer object. With the immediate flag on the command set to true, the execution of the action is triggered, and the GIS business objects and controls on the page are updated.
In the afterPhase() method, the PostBackPhaseListener uses the AJAXResponseRenderer and gets the XML response document from AJAXResponseRenderer.renderResponse(). This XML document is written to the response output stream using AJAXUtil.writeResponse(), the immediate flag is reset on the event sources, and FacesContext.responseComplete() is called.
The AJAXResponseRenderer class is responsible for iterating through the components in a form and calling the appropriate com.esri.adf.web.faces.renderkit.xml.ajax.AJAXRenderer class to render its state to XML. This XML is then parsed by the appropriate JavaScript functions to update the elements on the rendered page.
In the MapControl example, when the EsriMap object is rendered onto the browser page, this object registers a tag handler function named EsriControls.addPostBackTagHandler (map, EsriControls.maps[self.id].updateAsync). When the AJAXResponseRenderer is used to render an XML response, if the response document includes a <map> tag, the XML element is passed to the EsriMap.updateAsync() function. This function updates the map control—for example, it can update the image currently displayed on the map to display a zoomed in image. Similarly, other controls, such as EsriToc, EsriToolbar, EsriTask, and EsriOverview, have updateAsync() functions that update the appropriate controls during postback.

Use case 2: AJAXResponseRenderer (Map Zooms application)

This use case shows how to accomplish the following tasks:
  • Use a PhaseListener to change the state of a control
  • Have the change update any other control that is part of the Web context
  • Use the AJAXResponseRenderer object to help render the XML to update the controls on the browser page
When running the Map Zooms application, selecting a zoom factor less than 1.0 zooms into the map, while a factor greater than 1.0 will zoom out on the map.

mapZoom.jsp

The mapZoom.jsp page declares the controls to be used in this application. This application contains a single map control. It uses a drop-down menu to zoom in or out of the map based on a specified zoom factor. The following code sample shows how to use the specified zoom factor.
[Java]
 < select id = "zoomFactor" onchange = 
     "sendMapZoomRequest(document.getElementById('zoomFactor').value);" >  < option
     value = "0.2" > 0.2 <  / option >  < option value = "0.4" > 0.4 <  / option > 
     < option value = "0.6" > 0.6 <  / option >  < option value = "0.8" > 0.8 <  /
     option >  < option value = "1.0" selected = "true" > 1.0 <  / option >  <
     option value = "1.2" > 1.2 <  / option >  < option value = "1.4" > 1.4 <  /
     option >  < option value = "1.6" > 1.6 <  / option >  < option value = "1.8" >
     1.8 <  / option >  < option value = "2.0" > 2.0 <  / option >  <  / select >
The following screen shot is of the Map Zooms application.
The JavaScript sendMapZoomRequest() function is responsible for sending the request to the server with the zoom factor selected. The param string contains the required mapZoom=mapZoom parameter so that com.esri.arcgis.sample.mapzoom.MapZoomPhaseListener can determine if it is responsible for processing the request. This is shown in the following code sample.
[JavaScript]
var params = "mapZoom=mapZoom&formId=" + map.formId + "&mapId=" + map.id + 
    "&factor=" + factor + "&" + adf.Utils.buildRequestParams(map.formId);
The callback function to process the XML response is the EsriControls.processPostBack() function. This function is the central JavaScript function that delegates the processing of the response XML to each of the controls on the page based on the list of registered tag handlers. This is shown in the following code sample.
[Java]
var xmlHttp = adf.Utils.sendAjaxRequest(url, params, true,
    updateMapInformationResponse)

MapZoomPhaseListener.java

MapZoomPhaseListener is responsible for processing the request, getting the map control, zooming in and out of the map based on the factor selected, and using the AJAXResponseRenderer object to render the XML response. This PhaseListener also executes in the Apply Request Values phase as shown in the following code sample.
[Java]
public PhaseId getPhaseId(){
    return PhaseId.APPLY_REQUEST_VALUES;
}
Determine if this PhaseListener is responsible for processing the request as shown in the following code sample.
[XML]
if (! “mapZoom”.equals((String) paramMap.get(“mapZoom”)))
  return;
As with MapInformationPhaseListener, MapZoomPhaseListener uses the form and map control IDs to get to the MapControl and the GIS business objects that back the MapControl—namely the WebMap and the WebContext—as shown in the following code sample.
[XML]

UIComponent form = facesContext.getViewRoot().findComponent((String)paramMap.get(“formId”));
MapControl mapControl = (MapControl) form.findComponent((String) paramMap.get(“mapId”));
WebMap webMap = mapControl.getWebMap();
WebContext webContext = webMap.getWebContext();
Because AJAXResponseRenderer is used to update the map control on the page, an array of IDs must be created to determine the IDs of the controls that trigger the change to the application. In this case, it is the map, since the zoom operation is performed on the map. This is shown in the following code sample.
[Java]
Vector eventSources = new Vector();
eventSources.add(mapControl.getId());
Create an instance of the AJAXResponseRenderer class. When creating an instance of this object, pass in the faces context, the event sources, and the form that contain the controls you want to update as shown in the following code sample.
[Java]
AJAXResponseRenderer ajaxRenderer = new AJAXResponseRenderer(facesContext,
    eventSources, form);
The AJAXResponseRenderer class is instantiated before any change is made to the GIS business objects. This is done because, when the AJAXResponseRenderer is initialized, it finds all the com.esri.adf.web.faces.renderkit.xml.ajax.AJAXRenderer classes listed in WEB-INF/ajax-renderers.xml. It iterates through the controls in the form, and, based on the class name returned by AJAXRenderer.getControlClass(), it calls and stores the object returned by calling AJAXRenderer.getOriginalState(). The original state represents the state of the control before it may have been affected by the change.
Execute the business logic of zooming in and out of the map control based on the selected factor as shown in the following code sample.
[Java]
WebExtent webExtent = webMap.getCurrentExtent();
webExtent.expand(Double.parseDouble((String)paramMap.get(FACTOR)));
webMap.setCurrentExtent(webExtent);
Call com.esri.adf.web.data.WebContext.refresh() to update all the com.esri.adf.web.data.WebContextObservers as shown in the following code sample.
[Java]
webContext.refresh();
Now that all the business objects have been updated based on the zoom operation on the map, use the AJAXResponseRenderer instance to render the XML response document back as shown in the following code sample.
[Java]
Document doc = ajaxRenderer.renderResponse(facesContext);
When calling AjaxRenderer.renderResponse, AJAXResponseRenderer again iterates through the controls in the form, calls AJAXRenderer.renderAjaxResponse, and passes appropriate parameters for building the XML document. The response is written and the faces context implementation is notified that the response is complete as shown in the following code sample.
[Java]
AJAXUtil.writeResponse(facesContext, doc);
facesContext.responseComplete();
Since, in the calling function, the callback function for the request was set to EsriControls.processPostBack, this function now parses the XML response, finds the tags within the root <response> tag, and calls the appropriate tag handlers to process the XML tag. For example, the <map> tag is processed by the EsriMap.updateAsync() function.
Use case 2 is now complete.

Use case 3: Custom AJAXRenderers (Map Information 2 application)

This use case shows how to write a custom AJAXRenderer to render XML and how to use JavaScript to update custom content or custom components on the page. The Map Information application will be rewritten, but instead of triggering a call every time the EsriMap is updated, it will render an XML element as part of the XML response that is rendered as part of the postback response. The advantage is that since the control is part of the postback process, it does not require a special request-response cycle to update the map information.
As with use case 1, when running the Map Information 2 application, the extent and scale information are updated when you zoom in and out or pan the map.
The following screen shot is of the Map Information 2 application.

mapInformation2.jsp

The mapinformation2.jsp page is similar in layout to mapInformation.jsp, with the map control and table used to display the extent and scale information of the map. The init() function in the HTML body is called onload. The table and body information is shown in the following code sample.
[XML]
Map Information :<table>
  <tbody>
    <tr>
      <td>MinX :</td>
      <td>
        <span id="minx"></span>
      </td>
    </tr>
    <tr>
      <td>MinY :</td>
      <td>
        <span id="miny"></span>
      </td>
    </tr>
    <tr>
      <td>MaxX :</td>
      <td>
        <span id="maxx"></span>
      </td>
    </tr>
    <tr>
      <td>MaxY :</td>
      <td>
        <span id="maxy"></span>
      </td>
    </tr>
    <tr>
      <td>Scale :</td>
      <td>
        <span id="map-scale"></span>
      </td>
    </tr>
  </tbody>
</table>

mapInformation2.js

Register an init()function that will process the XML tag element <map-information-2> that is returned as part of the client side postback response as shown in the following code sample.
[Java]
EsriControls.addPostBackTagHandler("map-information-2", mapInformation2TagHandler);

MapInformation2Renderer.java

The com.esri.arcgis.sample.mapinformation2.MapInformation2Renderer class is an AJAXRenderer and is responsible for returning the map’s extent and scale information that is displayed in the table of the client. A control—for example, a map control—can have several AJAXRenderers, although it is com.esri.adf.web.faces.renderkit.xml.ajax.MapRenderer that is responsible for rendering the XML element that updates the map control. Because of this, you should not render <map>, <toc>, <task>, <toolbar>, or <overview> tags.
The AJAXResponseRenderer methods are described here in the order they are called.
The getControlClass() method returns the class of the component on the page for which it is responsible for rendering content. In this use case, AJAXResponseRenderer will identify the MapControl with which to work to obtain the information as shown in the following code sample.
[Java]
public Class getControlClass(){
    return MapControl.class;
}
AJAXResponseRenderer then calls the getOriginalState() method. This method returns an object representation of the state of the control, such that when later compared, it can be easily determined whether the state has changed. In this use case, the information on the browser page will be updated only if the map’s extent has changed; it will return the map’s current extent as its original state as shown in the following code sample.
[Java]
public Object getOriginalState(UIComponent component){
    MapControl mapControl = (MapControl)component;
    WebMap webMap = mapControl.getWebMap();
    return webMap.getCurrentExtent();
}
The renderAjaxResponse() method is called by AJAXResponseRenderer when AJAXResponseRenderer.renderResponse is called. In this method, check whether the extent of the map has changed. If it hasn't, do not render the <map-information-2> tag. Use this validation when writing custom AJAXRenderers to prevent unnecessary updates to the components rendered on the page as shown in the following code sample.
[Java]
if (currentExtent.equals((WebExtent)state))
    return ;
If the extent and scale have changed, render the minx, miny, maxx, maxy, and scale of the map to the XML. AJAXResponseRenderer passes reference to the parentElement of the XML document as shown in the following code sample. This renderer is responsible for rendering the <map-information-2> tag as a child of this parent tag.
[Java]
Element rootElement = XMLUtil.createElement("map-information-2", null, parentElement)
    ;
Use the com.esri.adf.web.util.XMLUtil functions to create the XML content elements as shown in the following code sample.
[XML]

XMLUtil.createElement("minx", String.valueOf(currentExtent.getMinX()), rootElement);
XMLUtil.createElement("miny", String.valueOf(currentExtent.getMinY()), rootElement);
XMLUtil.createElement("maxx", String.valueOf(currentExtent.getMaxX()), rootElement);
XMLUtil.createElement("maxy", String.valueOf(currentExtent.getMaxY()), rootElement);
XMLUtil.createElement("map-scale", String.valueOf(webMap.getMapScale()), rootElement);
The work of the MapInformation2Renderer is complete.

WEB-INF/ajax-renderers.xml

For the Java Web ADF framework to use this renderer, it must be included in the ajax-renderers.xml file. Declare a managed bean using the MapInformation2Renderer class as shown in the following code sample.
[Java]
 < managed - bean >  < managed - bean - name > ajaxMapInformation2Renderer <  /
     managed - bean - name >  < managed - bean - class >
     com.esri.arcgis.sample.mapinformation2.MapInformation2Renderer <  / managed -
     bean - class >  < managed - bean - scope > none <  / managed - bean - scope > 
     <  / managed - bean >
Next to the <list-entries> for the AJAXRenderers managed bean, add an entry whose value is the ajaxMapInformation2Renderer managed bean as shown in the following code sample.
[Java]
 < value > #{
    ajaxMapInformation2Renderer
}

 <  / value >
Implement the mapInformation2TagHandler() function that processes the <map-information-2> XML tag and updates the appropriate elements on the HTML page. The EsriControls.processPostBack() function passes the <map-information-2> tag element and the list of eventSources as arguments to this function as shown in the following code sample.
[XML]

function mapInformation2TagHandler(xml, eventSources) {
  document.getElementById("minx").innerHTML = xml.getElementsByTagName("minx").item(0).firstChild.nodeValue;
  document.getElementById("miny").innerHTML = xml.getElementsByTagName("miny").item(0).firstChild.nodeValue;
  document.getElementById("maxx").innerHTML = xml.getElementsByTagName("maxx").item(0).firstChild.nodeValue;
  document.getElementById("maxy").innerHTML = xml.getElementsByTagName("maxy").item(0).firstChild.nodeValue;
  document.getElementById("map-scale").innerHTML = 
xml.getElementsByTagName("map-scale").item(0).firstChild.nodeValue;
}


See Also:

JavaEE and JSF Technology
AJAX: A New Approach to Web Applications
The JSF application lifecycle
DOM2 reference with examples
Developing Web applications with JSF