Welcome!

SOA & WOA Authors: Peter Silva, Maureen O'Gara, Tony Bishop, Mark O'Neill, Yeshim Deniz

Related Topics: Java, AJAX & REA, Web 2.0

Java: Article

Enterprise Mashup Services

Part 2: Combining JSF and mashup services to make mashup components

The MapModel and MapBean
The MapModel object (Listing 7) defines two abstract methods: onSelect and onMoveEnd. The onSelect method is called when a user selects a marker on the map, and the onMoveEnd method is invoked after a user completes a zoom or pan operation.

abstract public String onSelect(GeoPoint pt);

abstract public String onMoveEnd(String lat, String lng, String zoom);

Both methods represent steps in a simple template or behavior pattern in which behavior is implemented by a subclass of the MapModel object (Figure 5).

The onSelect and onMoveEnd methods are called by the selectPoint and moveEnd template methods, respectively. Both methods extract values for parameters from a request string, pass those values onto the methods that inject behavior (for example, onMove or onSelect) into the encapsulated method, and return a response using the writeResponse method.

The moveEnd and selectPoint methods are invoked by the faces/dynamic/mapbean/moveEnd and faces/dynamic/mapbean/selectPoint URLs, respectively. The addSelectPointListener and addMoveEndListener JavaScript functions defined in the mapScript.js file (Listing 9) associate a GEvent listener with the current GMap object. When called, a listener posts a request to the URL that invokes either the moveEnd or selectPoint method. In this example, Gevent listeners are generated on marker selections or pan and zoom operations. For more information on Gevent listeners or other facets of the Google Maps API, refer to the Google Maps API documentation (www.google.com/apis/maps).

The concrete implementation of the MapModel object used in this example is com.thepeninsulasedge.view.managed.MapBean (Listing 10). The class defines an onSelect method that extracts a message or string contained in a GeoPoint object, which is associated with a marker on the map. The extracted message is then written as a response to the initial XMLHttpRequest object using the writeResponse method, and displayed in an info window on the map (Figure 6).

The onMoveEnd method updates a display that shows the coordinates of the map's center and the current level of magnification (Figure 7).

Besides providing methods to respond to JavaScript events, the MapBean also defines three action methods - addPointToMap, removeSelectedPoint, and clearMap - that are executed by command components. These methods demonstrate how the tpe:map component can be integrated with existing JSF components. For example, the addPointToMap method adds a new point to the map by manipulating the collection of GeoPoint objects contained in the MapBean. The method creates a new GeoPoint instance from an address and adds the point to the MapBean's current list of points. The method is executed by h:commandButton and the address is provided by an h:inputText field (See Listing 11).

GeoPoints
Each GeoPoint object in the MapBean is associated with a marker on a map and located by latitude and longitude. (To better understand the relationship between GeoPoint objects and the MapBean, see the diagram in Figure 8.)

Thus, when a user clicks a marker, the corresponding GeoPoint object is located in the MapBean by finding a GeoPoint object with a matching set of coordinates. The following Predicate (see the Apache Commons Collection at http://jakarta.apache.org/commons/collections/) is used to perform the evaluation between latitude and longitude and a corresponding GeoPoint object. The Predicate performs this evaluation while iterating through a collection of GeoPoint objects.

   public static Predicate findPredicate(final String lat, final String lng) {
     return new Predicate() {
       public boolean evaluate(Object obj) {
     if (!(obj instanceof GeoPoint))
       return false;
     GeoPoint pt = (GeoPoint)obj;
     if (pt.getLat().equals(lat) && pt.getLng().equals(lng)) {
       return true;
     } else {
       return false;
     }
    }
     };
   }

The GeoPointUtil class also provides a convenient way to create new instances of GeoPoint objects using the Yahoo! Geocoding API. The technique simply parses coordinates from an XML result generated by a request and uses the coordinates to create a new instance. The result is parsed with the Apache Commons Digester (http://jakarta.apache.org/commons/digester/).

The MapRenderer
The HTML and JavaScript in Listing 6 is the code used to create a new instance of the GMap2 object - the JavaScript object that represents a map in the Google Maps API. The code also ties the JavaScript used to consume the Google Maps API to the Java code in the MapBean. The com.thepeninsulasedge.components.MapRenderer class (Listing 3) is responsible for producing the markup shown in Listing 6. To understand which method in the MapRenderer class produced a specific snippet of JavaScript or HTML, look at the comments generated by the MapRenderer class in Listing 6. Note that only the load function used to instantiate the GMap2 object and a set of variables are dynamically generated in the MapRenderer class. This is done to ensure that each tpe:map component has a unique load function and set variables, allowing multiple tpe:map components to be used in a single page. Uniqueness is guaranteed by appending the component's client identifier to the name associated with the dynamically generated variable or function. According to JSR 127, each server-side component in JSF is guaranteed a unique client identifier.

The MapRenderer class relies on functions defined in the mapScripts.js file (Listing 9). These functions limit the need to hardcode JavaScript into the class and define essential functions such as addSelectPointListener and addMoveEndEvent. For the JavaScript generated by the MapRenenderer class to use functions defined in mapScripts.js, the file must first be imported. This is done with Shale Remoting. The linkJavascript method in org.apache.shale.remoting.XhtmlHelper is used for the import statement for the mapScripts.js file:

<script type="text/javascript"
src="/GoogleMapsAndDWR-JSFView-context-root/faces/static/com/thepeninsulasedge/
components/scripts/mapScripts.js">
</script>

The script import provides a reference to the mapScript.js file relative to the Web applications class path. Thus, the file specified is located under the package structure com/thepeninsulasedge/components/scripts/. A similar import is generated for the prototype.js file.

Conclusion
Consuming mashup services in the enterprise is a reality, and encapsulating mashup APIs with custom JSF components provides an elegant solution for packaging and reusing these services. The example in this article consolidated the complex markup and script shown in Listing 6 into a simple and concise component that amounted to a single XML tag. Imagine that - the power of Google Maps packaged in a simple component. Moreover, the componentization of the Google Maps API, as well as the linkage between JavaScript events and the JSF managed bean facility, makes it relatively easy to tie Google Maps to J2EE services such as EJB 3.0. The result of this blending of external mashups, Shale, and JSF is an enterprise-ready mashup service in very accessible package. To learn more about the technologies referenced in this article, please refer to the references provided.

References

More Stories By Ric Smith

Ric Smith is director, business and product strategy at Kaazing. provides Kaazing Corporation with a wealth of experience in product management and consulting for enterprise products and services. Prior to joining Kaazing, Ric was a principal product manager for Oracle's Fusion Middleware at Oracle's Headquarters in Redwood Shores, CA. In his role as a Principal Product Manager he was responsible for the evangelism and product direction of Oracle's AJAX and Java EE Web Tier offerings. Before joining the Fusion Middleware team, Ric worked for Oracle's consulting business as a principal consultant where he led development of mission-critical applications for prominent organizations within the defense/intelligence industry. In addition, Ric won consecutive awards for technical achievement for each year of his tenure as a consultant. Ric is a frequent speaker at international events and has written articles featured in leading industry publications such as Java Developer's Journal and AJAXWorld Magazine. He is also a representative to the OpenAjax Alliance and an honors graduate of the University of Arizona.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.