|
By Jai Suri and Marina Sum, August 24, 2006
|
|
|
Lately, with the availability of developer APIs from Web-service giants, such as Google, Yahoo, eBay, and Amazon, Web mashups have gained a lot of attention. According to ProgrammableWeb, a Web mashup is "a Web page or application that combines data from two or more external online sources. The external sources are typically other Web sites and their data may be obtained by the mashup developer in various ways, including, but not limited to APIs, XML feeds, and screenscraping."
To build a mashup, you need access to a minimum of two data sources that can be combined to create a service, which is not otherwise available from either source. Popular mashups, such as Housing Maps and Chicago Crime, make use of a geospatial data service, such as Google Maps or Yahoo Maps, as one of those sources. Other mashups offer product listings, ratings, auction prices, and so forth by combining catalog data from Amazon with auction data from eBay.
This article describes how to build a mashup portlet that can aggregate geospatial data from data sources and combine it with an online mapping service based on Asynchronous JavaScript and XML (Ajax) to generate a mashup. Included are the portlet's source code and techniques for deploying the portlet to Sun Java System Portal Server 7 (henceforth, Portal Server). At the end of the article is a list of reference resources.
Contents
Introducing Mashups and Portlets
Because portlets can incorporate mashups, the latter are a natural fit for portals. A portlet can fetch content from various data sources to create a mashup. Subsequently, the portal can personalize that data so that its users can have their own mashups with data sources that suit their individual needs, hence saving a major task in the development cycle.
A portal with business monitoring mashup portlets can act as a dashboard for tracking performance indicators that are grouped together for easy visual representation of early warnings and exceptions. Accordingly, executives can configure their dashboards to monitor performance and create personalized mashups with just a few clicks.
As an example, a manufacturing manager can create a mashup portlet that shows on a map the inventory status of all the plant units across the geography. The map displays the locations with critical inventory status with a unique icon that flags the need for corrective measures. Clicking that icon redirects the manager into the workflow of a Sun Java Composite Application Platform Suite (Java CAPS) implementation, wherein he can take the appropriate action to correct the inventory abnormalities.
Creating a Mashup Portlet
This section shows you how to create a sample portlet, named MashupMapPortlet, that overlays geospatial information from data sources on an Ajax-enabled map. See Figure 1.
Figure 1: MashupMapPortlet (Click image for larger view.) |
You can download the source code and binary Web archive (WAR) file, which will later be posted to the Portal Open Source Project Repository.
Using Sample Data Sources
As sample data sources, use the following:
- A public GeoRSS feed from the USGS Earthquake Center
- A custom GeoRSS feed that shows the phone directory of Sun Microsystems sales offices throughout the world. This is an unofficial, temporary feed only and might be offline any time.
For the Ajax-enabled map, use Google Maps, Yahoo Maps, or MapQuest. Each of these map services provides comprehensive developer APIs for generating geospatial map mashups. For simplicity, because Yahoo Maps offers an easy API for GeoRSS feeds, you will use that API for this sample portlet.
For your application, evaluate all the online mapping-service APIs and choose the one that best suits you. For example, Google Maps does not provide any routing API; MapQuest does. On the other hand, Google Maps is fast and easy to use because it supports Ajax-based drag-and-zoom.
Another important point to consider is the registration and licensing requirements of those services. Each service has unique requirements so pick the one that best meets your portal deployment needs. Yahoo Maps offers free registration and a unique application ID to be sent with each Web services request. That's what you will use with the sample portlet.
Creating the Portlet Class
As a first step, create the portlet class and name it MashupMapPortlet, as described in this section.
Definition
First, define the portlet class in MashupMapPortlet.java, as follows.
package com.sun.portlets.mashups;
import javax.portlet.*;
import java.io.*;
public class MashupMapPortlet extends GenericPortlet {
|
init() Method
In the portlet's init() method, initialize the portlet configuration and fetch the JSP directory location from the jspDir portlet init configuration parameter in the portlet.xml file, as follows.
public class MashupMapPortlet extends GenericPortlet {
private String jspDir = null;
public void init() {
PortletConfig config = getPortletConfig();
jspDir = config.getInitParameter( "jspDir" );
}
|
doView() Method
Create the doView() method of the portlet, as follows.
public void doView(RenderRequest req, RenderResponse res) throws IOException,
PortletException {
PortletPreferences prefs = req.getPreferences();
res.setContentType(req.getResponseContentType());
req.setAttribute( "mashupUrls",
prefs.getValues( "mashupUrls", null ) );
PortletRequestDispatcher prd =
getPortletContext().getRequestDispatcher( jspDir + "view.jsp");
prd.include(req, res);
}
|
This is a simple method whose only task is to fetch URLs for the feeds from the user's personal preferences and pass those URLs in an array to the view.jsp file. That file, described later in this article, creates the mashup according to the URLs it fetches from a request. The user's personal preferences are stored in a collection attribute, mashupUrls, in the portlet preferences that are defined in the portlet.xml file.
doEdit() Method
Next, create the doEdit() method, as follows.
public void doEdit(RenderRequest req, RenderResponse res) throws IOException,
PortletException {
PortletPreferences prefs = req.getPreferences();
res.setContentType(req.getResponseContentType());
req.setAttribute( "mashupUrls", prefs.getValues( "mashupUrls", null ) );
PortletRequestDispatcher prd =
getPortletContext().getRequestDispatcher( jspDir + "edit.jsp");
prd.include(req, res);
}
|
This method, called when the portlet enters edit mode, displays the edit form.
processAction() Method
Finally, create the processAction() method that enables users to store their preferences, as follows.
public void processAction(ActionRequest req, ActionResponse res) throws
IOException, PortletException {
PortletPreferences prefs = req.getPreferences();
String [] urls = req.getParameterValues("mashupUrls");
prefs.setValues( "mashupUrls", urls );
try{
prefs.store();
req.setAttribute( "edit_msg", "Preferences saved" );
res.setPortletMode(PortletMode.VIEW);
} catch( ValidatorException ve ) {
req.setAttribute( "edit_msg", ve.getMessage() );
res.setPortletMode(PortletMode.EDIT);
}
}
|
Note: The preceding code samples serve as examples only and do not do a complete job of checking for runtime errors. To use this portlet in a production environment, you must add more thorough error-handling tasks.
Creating the Portlet JSP Pages
Now on to the fun partcreating the mashup itself. Start with the JSP pages.
view.jsp
Create the JSP page view.jsp, which generates the mashup map view, as follows.
<%@ page import="javax.portlet.PortletURL" %>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%
String [] mashupUrls = (String[])request.getAttribute("mashupUrls");
%>
<portlet:defineObjects/>
<script type="text/javascript"
src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=YahooDemo"></script>
<style type="text/css">
#mapContainer {
height: 450px;
width: 100%;
}
</style>
<div id="mapContainer"></div>
<script type="text/javascript">
// Create a map object
var map = new YMap(document.getElementById('mapContainer'));
// Add a map type control
map.addTypeControl();
// Add a pan control
map.addPanControl();
// Add a slider zoom control
map.addZoomLong();
// Set map type to either of: YAHOO_MAP_SAT YAHOO_MAP_HYB YAHOO_MAP_REG
map.setMapType(YAHOO_MAP_REG);
<%
for (int i=0;i<mashupUrls.length;i++) {
%>
map.addOverlay(new YGeoRSS('<%= mashupUrls[i]%>'));
<%
}
%>
</script>
|
The first two lines are standard for portlet JSP pages.
Next, fetch the URL array from the declarations request, as follows:
<%
String [] mashupUrls = (String[])request.getAttribute("mashupUrls");
%>
|
When an initial request for the portlet is made, the doView() method adds this array to the request as an attribute.
The rest of the code in view.jsp is mostly JavaScript code. For an understanding of that code, you must learn the basics of JavaScript, Dynamic HTML (DHTML), and Document Object Model (DOM).
Yahoo Maps JavaScript Ajax API
Recall that, for this sample portlet, you use the Yahoo Maps JavaScript Ajax API to create a mashup. Follow these steps:
- Include the following statements to fetch the Yahoo Map JavaScript library.
<script type="text/javascript"
src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=YahooDemo"></script>
|
Note the appid parameter, whose value in this sample is YahooDemo. Be sure to customize it as your own registered Yahoo application ID. Do not use this ID except for learning purposes.
- Create a placeholder
DIV named mapContainer to hold the map object and define a CSS style for DIV, as follows.
<style type="text/css">
#mapContainer {
height: 450px;
width: 100%;
}
</style>
|
- Create and initialize the Yahoo map object, with controls for map type, pan, and slider zoom, as follows.
// Create a map object
var map = new YMap(document.getElementById('mapContainer'));
// Add a map type control
map.addTypeControl();
// Add a pan control
map.addPanControl();
// Add a slider zoom control
map.addZoomLong();
// Set map type to either of: YAHOO_MAP_SAT YAHOO_MAP_HYB YAHOO_MAP_REG
map.setMapType(YAHOO_MAP_REG);
|
- Add the GeoRSS feeds from the user's preferences with the API's JavaScript object
YGeoRSS(URL) to the map, as follows.
<%
for (int i=0;i<mashupUrls.length;i++) {
%>
map.addOverlay(new YGeoRSS('<%= mashupUrls[i]%>'));
<%
}
%>
|
edit.jsp
The edit page, edit.jsp, contains a simple edit form with input fields for users to customize their mashups by adding, deleting, and editing the GeoRSS feed URLs. For the source code, see the edit.jsp file in the download bundle.
Creating the portlet.xml File
Finally, create the portlet deployment descriptor as a code segment in the portlet.xml file, as follows.
<portlet>
<portlet-name>MashupMapPortlet</portlet-name>
<display-name>Mashup Portlet</display-name>
<portlet-class>com.sun.portlets.mashups.MashupMapPortlet</portlet-class>
<init-param>
<name>jspDir</name>
<value>/WEB-INF/jsp/</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>MashupMapPortlet</title>
<short-title>Mashup</short-title>
<keywords>Mashup</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>mashupUrls</name>
<value>http://earthquake.usgs.gov/eqcenter/recenteqsww/catalogs/
eqs7day-M2.5.xml</value>
<value>http://jaisuri.googlepages.com/offices.xml</value>
</preference>
</portlet-preferences>
</portlet>
|
Here, you define an init-param parameter named jspDir to hold the directory location of the JSP files. You also create a portlet preference, mashupUrls, which is a collection to hold the personalized GeoRSS feed URLs for each of the users. The default URLs are shown under <value>.
Packaging and Deploying the Portlet
The MashupMapPortlet sample includes a WAR file and the source code as an open-source NetBeans IDE project.
Deploying the Sample
To deploy MashupMapPortlet on Portal Server, ensure that you have a working version of Portal Server on your system and then follow these steps:
- Download the sample.
- Unzip the files to a temporary directory.
- Type the following command line (all on one line) to deploy the WAR file to Portal Server:
% psadmin deploy-portlet -u uid -f password-filename {-g|-d dn} -p portal-ID WAR-filename
For example:
% /opt/SUNWportal/bin/psadmin deploy-portlet -u "uid=amAdmin,ou=People,dc=sun,dc=com" -f /tmp/password -p portal1 -d "o=DeveloperSample,dc=sun,dc=com" /tmp/MashupMapPortlet/dist/MashupMapPortlet.war
For details on the command psadmin deploy-portlet, see Chapter 6 of the Sun Java System Portal Server 7 Command-Line Reference.
- Type the following command line (all on one line) to update the display profile so as to create a channel for
MashupMapPortlet and add that channel to PortletSamplesTabPanelContainer:
% psadmin modify-dp -u uid -f password-filename {-g|-d dn} -p portal-ID --combine filename
For example:
% /opt/SUNWportal/bin/psadmin modify-dp -u "uid=amAdmin,ou=People,dc=sun,dc=com" -f /tmp/password -m -d "o=DeveloperSample,dc=sun,dc=com" -p portal1 --combine /tmp/MashupMapPortlet/MashupMapPortlet-dp.xml
Building the Sample
To build the sample:
- Open
MashupMapPortlet as a Web application project in the NetBeans IDE.
- Right-click the project name in the left navigation area and choose Clean and Build Project from the context menu.
The NetBeans IDE builds the project and generates a WAR file in the project's dist directory.
Viewing the Portlet
If you deploy the portlet in the DeveloperSample organization and then log in as a user of that organization, a user named developer (password: developer) exists by default at DeveloperSample. Log in as developer, navigate to the Portlet Samples tab, and you see MashupMapPortlet on the portal page.
Caveats
Bear in mind the following caveats on mashup portlets:
- Because most of the mashup processing occurs in third-party JavaScript on the client browser, that browser must have access to the Web, either directly or through a proxy, and must be able to download and run JavaScript from Yahoo or another online mapping service.
- All the GeoRSS feed URLs must be publicly accessible on the Web, as required by the
YGeoRSS Yahoo Maps API. You can work around this constraint by creating your own GeoRSS parser JavaScript object.
- If your portal is already using Ajax (that is, an
XMLHttpRequest object), you might encounter cross-domain Ajax issues. A future article in this series will address that topic.
- The Back buttons on browsers can present a problem with Ajax-based Web applications. As a resolution, you must manipulate the state in your portlet.
Conclusion
Bringing together data from different sources and visually representing it on a draggable and zoomable map, as in mashup portlets, renders a rich, robust user experience. However, the related technologies are still in largely uncharted territory. Even though JavaScript and Ajax are rapidly catching up as the Web development technique of choice, open issues abound. In particular, standardization of the format for geospatial data feeds remains in debate.
Nonetheless, creating mashups is an effective and dynamic technique for enhancing the productivity of your portal users. Take it for a spin!
References
|
Jai Suri, a member of the Sun Java Portal Server engineering team, is currently involved in developing next-generation portlet containers based on AJAX and DHTML. For the latest AJAX features of Sun Java Portal Server, visit his screencast.
|
Marina Sum is a staff writer for Sun Developer Network. She has been writing for Sun since 1989, mostly in the technical arena. Marina blogs on Sun products, technologies, events, and publications.
|
Get AJAX Training
Check out these new courses:
|
|