Building Mashup Applications using jMaki

Contributed and maintained by Sang Shin & Doris Chen, Sun Microsystems, www.javapassion.com/ajaxcodecamp

   

jMaki is all about enabling Java developers to use JavaScript in their Java based applications as either a JSP tag library or a JSF component. jMaki uses the best parts of Java and the best parts of JavaScript to deliver a rich Ajax style widgets.  jMaki currently provides bootstrap widgets for many components from Dojo, Script.aculo.us, Yahoo UI Widgets, Spry, DHTML Goodies, and Google. jMaki provides a common interfaces to these widget libraries and allows you to use these libraries together in the same page.

This hands-on lab takes you through the basics of using jMaki widgets for developing highly responsive and interactive AJAX-based web applications. This document is designed to get you going as quickly as possible.


Expected duration: 100 minutes


Prerequisites

This hands-on lab assumes you have some basic knowledge of, or programming experience with, the following technologies.

Software Needed

Before you begin, you need to install the following software on your computer.  Please note that this lab requires NetBeans IDE 5.5.  If you have only NetBeans IDE 5.0 on your computer, you will have to install NetBeans 5.5.  You don't have to uninstall NetBeans IDE 5.0 before you install NetBeans IDE 5.5 -  NetBeans IDE 5.0 and NetBeans IDE 5.5 coexist on a single computer without a problem.



Change Log



Lab Exercises


Once software mentioned above are downloaded and installed, you will not need internet connection to do this hands-on lab.


Exercise 1: Build RSS Feed Application

In this exercise, you are going to learn how to use Yahoo Data Table widget and Block List widget to display the data from an external RSS feed.  You are also going to learn how to modify the Block List widget so that it displays with additonal data such as date information and with a different style, for example, different font size.  Usage of external service is enabled through XmlHttpProxy feature of jMaki technology.

This exercise is based on Arun Gupta's Creating Mashups with jMaki - Display RSS feed in jMaki Widgets screencast blog. 


(1.1) Create a new jMaki NetBeans project

0. Start NetBeans 5.5 IDE (if you have not done so yet)
1. Create a new NetBeans project


Figure-1.11: Create Web Application

2. Set a project name.

Figure-1.12: Name and Location pane

3. Choose server


4. Select jMaki Ajax Framework.

Figure-1.13: Choose jMaki Ajax Framework

                                                                                                                        return to top of the exercise

(1.2) Add "Yahoo Data Table"  widget


1.  Add jMaki Yahoo Data Table widget.

Figure-1.14: Data Table widget

2. Build and run the project

Figure-1.15: Run the application

Figure-1.16: Run the project with static (hard-coded) data

                                                                                                                        return to top of the exercise

(1.3) Configure "Yahoo Data Table" widget with external RSS feed service


1. Observe a set of pre-configured RSS feeds.

Figure-1.31: Check the xhp.json file

2. Replace the static data of the database table with RSS feed.
                    <a:widget name="yahoo.dataTable"  service="xhp?id=rss" />
Code-1.32: Specify external service


Figure-1.33: Use external service for the data table

3. Save the change.


4. Display the result

Figure-1.34: Datatable widget is now displayed with RSS fed data

4. Change the number of entries to be displayed.

<%@ taglib prefix="a" uri="http://jmaki/v1.0/jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
    <head>
        <link rel="stylesheet" href="jmaki-2column-footer.css" type="text/css"></link>
        <title>Page Title</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body>
        <div class="border">
           
            <div class="header">
                <div class="banner">Application Name</div>
               
                <div class="subheader">
                   
                    <div>
                        <a href="mailto:feedback@youraddress">Feedback</a> |
                        <a href="#">Site Map</a> |
                        <a href="#">Home</a>
                    </div>
                   
                </div> <!-- sub-header -->
            </div> <!-- header -->

            <div class="main">
                <div class="rightColumn" style="height:400px">
                    <a:widget name="yahoo.dataTable"
                              service="xhp?id=rss&count=3" />
                   
                   
                   
                </div> <!-- end leftColumn -->

                <div class="leftColumn" style="height:400px">
                   
                    Left Column
                   
                </div> <!-- leftColumn -->

            </div> <!-- main -->
            <div class="footer">Footer</div>
        </div> <!-- border -->
    </body>
</html>
Code-1.35: Specify number of entries to be displayed

Figiure-1.36: Specify number of entries

5. Display the result

Figure-1.37: RSS fed data table with 3 entries

                                                                                                                        return to top of the exercise

(1.4) Add "Block List" widget to the left column


1. Remove "Lef Column" string, which is located around line number 38.
2. Drag the Block List widget from the jMaki Widget section and drop it in the left column area.  (Figure-1.41 below)


Figure-1.41: Add Block List widget to the left column area

3. Set the Block List widget with external service.

<%@ taglib prefix="a" uri="http://jmaki/v1.0/jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
    <head>
        <link rel="stylesheet" href="jmaki-2column-footer.css" type="text/css"></link>
        <title>Page Title</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body>
        <div class="border">
           
            <div class="header">
                <div class="banner">Application Name</div>
               
                <div class="subheader">
                   
                    <div>
                        <a href="mailto:feedback@youraddress">Feedback</a> |
                        <a href="#">Site Map</a> |
                        <a href="#">Home</a>
                    </div>
                   
                </div> <!-- sub-header -->
            </div> <!-- header -->

            <div class="main">
                <div class="rightColumn" style="height:400px">
                    <a:widget name="yahoo.dataTable"
                              service="xhp?id=rss&count=3" />
                   
                   
                   
                </div> <!-- end leftColumn -->

                <div class="leftColumn" style="height:400px">
                    <a:widget name="jmaki.blockList"   service="xhp?id=rss&count=3" />
                   
                   
                   
                </div> <!-- leftColumn -->

            </div> <!-- main -->
            <div class="footer">Footer</div>
        </div> <!-- border -->
    </body>
</html>
Figure-1.42: Set the service attribute for the Block List widget

Figure-1.43: Set service attribute with external service

4. Display the result


Figure-1.44: Block List widget displays RSS fed data

                                                                                                                        return to top of the exercise

(1.5) Modify the Block List widget


1. Open component.htm of the Block List widget
<div id="${uuid}" class="jmakiStack jmakiBackround">
    <div id="${uuid}_content" class="jmakiStackContent">
        <ul id="${uuid}_list">
        </ul>
    </div>

</div>
<div id="${uuid}_nav" class="jmakiStackNav">
        <div id="${uuid}_previous" class="previous">Previoius</div>
        <div id="${uuid}_mid" class="mid"></div>
        <div id="${uuid}_next" class="next">Next</div>
</div>
<div id="${uuid}_template" style="display:none" class="jmakiStackItem">
    <a href="@{link}">@{title}</a><br/>
    <br/>@{date}<br/>
    @{description}<br/>
</div>
Code-1.51: Date information is added to the widget

Figure-1.52: Date information is added to the component.htm

2. Display the result


Figure-1.53: Date information is now displayed

3. Modify the style of the Block List widget

<div id="${uuid}" class="jmakiStack jmakiBackround">
    <div id="${uuid}_content" class="jmakiStackContent">
        <ul id="${uuid}_list">
        </ul>
    </div>

</div>
<div id="${uuid}_nav" class="jmakiStackNav">
        <div id="${uuid}_previous" class="previous">Previoius</div>
        <div id="${uuid}_mid" class="mid"></div>
        <div id="${uuid}_next" class="next">Next</div>
</div>
<div id="${uuid}_template" style="display:none" class="jmakiStackItem">
    <a href="@{link}" style="font-size: 16pt">@{title}</a><br/>
    <br/>@{date}<br/>
    @{description}<br/>
</div>
Code-1.55: Style is changed


Code-1.56: Style is changed

4. Display the result

Figure-1.57: Result

                                                                                                                        return to top of the exercise

Solution


The solution is provided as a ready-to-open-and-build NetBeans project as <LAB_UNZIPPED_DIRECTORY>/ajaxjmakimashup/samples/jmaki_mashup.

Summary

In this exercise, you learned how to use Data Table widget and Block List widget.  You learned how to change these two widgets so that they use the external services.
   
                                                                                                                                   Return to the top


Exercise 2: Build Yahoo and Google Map mashup application

In this exercise, you are going to learn how to use Yahoo Map, Google Map, Yahoo GeoCoder widgets to build a simple yet practical application in which Yhaoo Map and Google Map widgets display the map information that is specified in the Yahoo GeoCoder widget by the user.  This feature is based on the "Publish and Subscribe" event model of jMaki technology.

This exercise is based on Arun Gupta's Creating Mashups with jMaki - Mashing up the Maps screencast blog.  Another blog, Fun with jMaki:Using the Yahoo Geocoder service with the Dojo Combobox, contains some explanation on how things work.

(2.1) Build and run jMaki NetBeans project

1. Create a new jMaki NetBeans project


Figure-2.11: Name and Location pane


2. Select jMaki Ajax Framework.


Figure-2.13: Select jMaki Ajax Framework

3. Add three widgets.


Figure-2.21: Add three widgets to the project


4. Run the project


Figure-2.31: Run the CityLocator project

5. Enter city information in the GeoCoder field.


Figure-2.32: Result

                                                                                                                        return to top of the exercise


(2.2) Control flow


1.  User enters the location value, for example, "Boston, MA", into the Location field in the bottom of the page and click Get Coordiates button.   This is based on the Yahoo GeoCoder widget (which is represented as yahoo.geocoder) as shown below. The widget is sending a request to Yahoo Geocoder service on the net and retrieves the coordinates of the location.

<%@ taglib prefix="a" uri="http://jmaki/v1.0/jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
    <head>
        <link rel="stylesheet" href="jmaki-2column-footer.css" type="text/css"></link>
        <title>Page Title</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body>
        <div class="border">
           
            <div class="header">
                <div class="banner">Application Name</div>
               
                <div class="subheader">
                   
                    <div>
                        <a href="mailto:feedback@youraddress">Feedback</a> |
                        <a href="#">Site Map</a> |
                        <a href="#">Home</a>
                    </div>
                   
                </div> <!-- sub-header -->
            </div> <!-- header -->

            <div class="main">
                <div class="rightColumn" style="height:400px">
                    <a:widget  name="google.map"
                               args="{ centerLat : 37.4041960114344,
                               centerLon : -122.008194923401 }" />
                              
                              
                              
                </div> <!-- end leftColumn -->
               
                <div class="leftColumn" style="height:400px">
                    <a:widget  name="yahoo.map"
                               args="{ centerLat : 37.4041960114344,
                               centerLon : -122.008194923401 }" />
                              
                              
                              
                </div> <!-- leftColumn -->
               
            </div> <!-- main -->
            <div class="footer"><a:widget name="yahoo.geocoder" />
            </div>
        </div> <!-- border -->
    </body>
</html>

2. The component.htm of  CityLocator->Web Pages->resources->yahoo->geocoder, which is layout page of the Geocoder widget, below indicates that when the button is clicked, it will call jmaki.attributes.get('${uuid}').getCoordinates().

<div id="${uuid}">
    <form onsubmit="jmaki.attributes.get('${uuid}').getCoordinates();return false;">
        <b>Location:</b>  <input type="text" id="${uuid}_location">
        <input type="button" value="Get Coordinates" onclick="jmaki.attributes.get('${uuid}').getCoordinates();">
    </form>
</div>
component.htm of Geocoder widget

3. The component.js under CityLocator->Web Pages->resources->yahoo->geocoder contains getCoordinates function (code fragment that is highlighted in bold and blue-colored font), in which it makes an Ajax call to the Yahoo geocoder service to retrieve the coordiates. 
4. When the coordinates data is retrieved, the Ajax callback function postProcess(req) is invoked.  Inside the postProcess(req) function, /yahoo/geocoder/onGeocode is published as a topic.

// define the namespaces
jmaki.namespace("jmaki.widgets.yahoo.geocoder");

/**
 * Yahoo Geocoder Widget
 *      This widget lets you find geocordinates using the XMLHttpProxy using
 *      the Yahoo Geocoder service
 *
 * @author Greg Murray
 *          (original author)
 * @author Ahmad M. Zawawi <ahmad.zawawi@gmail.com> 
 *          (Updated to new yahoo jmaki widget standard)
 *
 * @see http://developer.yahoo.com/maps/rest/V1/geocode.html
 */
jmaki.widgets.yahoo.geocoder.Widget = function(wargs) {
   
    var topic = "/yahoo/geocoder";
    var uuid = wargs.uuid;
    var self = this;
   
    // we run on the xhp now
    var service = jmaki.xhp;
   
    //overide topic name if needed
    if (wargs.args && wargs.args.topic) {
        topic = wargs.args.topic;
    }
   
   
   
    var location;
   
    /**
     */
    this.getCoordinates = function() {
        location = encodeURIComponent(document.getElementById(uuid + "_location").value);
        var encodedLocation = encodeURIComponent("location=" + location);       
        var url = service + "?id=yahoogeocoder&urlparams=" + encodedLocation;       
        jmaki.doAjax({url: url, callback: function(req) { var _req=req; postProcess(_req);}});
    }
   
    /**
     */
    function postProcess(req) {
        if (req.readyState == 4) {
            if (req.status == 200) {
                var v = {success:false};
                if(req.responseText.length > 0) {
                    var response = eval("(" + req.responseText + ")");
                    var coordinates = response.coordinates;
                    v = {success:true,results:coordinates};
                   
                    //for compatibility (deprecated): we leave this one for a while
                    jmaki.publish(topic, coordinates); 
                }
                //the new format is here (as in v)
                //with status flag sent
                jmaki.publish(topic + "/onGeocode", {id: uuid, value:v} )               
            }
        }
       
    }
   
}
component.js of the Geocoder widget

5 The system-glue.js below indicates that jmaki.listeners.geocoderListener is added as an event listener that gets invoked when events are published to topic /yahoo/geocoder$.  (Remember that the event is published to the /yahoo/geocoder/onGeocode topic in the previous step.)
6. The
jmaki.listeners.geocoderListener displays the map with the coordinates returned from the Yahoo Geocoder service for any Yahoo map and Google map widgets.

jmaki.namespace("jmaki.listeners");
  
jmaki.listeners.geocoderListener = function(coordinates) {
        var keys = jmaki.attributes.keys();
        // scan the widgets for all yahoo maps
        for (var l = 0; l < keys.length; l++) {
            if (jmaki.widgets.yahoo &&  jmaki.widgets.yahoo.map &&
                jmaki.widgets.yahoo.map.Widget &&
                jmaki.attributes.get(keys[l]) instanceof jmaki.widgets.yahoo.map.Widget) {
                var _map = jmaki.attributes.get(keys[l]).map;
                var centerPoint = new YGeoPoint(coordinates[0].latitude,coordinates[0].longitude);
                var marker = new YMarker(centerPoint);
                var txt = '<div style="width:160px;height:50px;"><b>' + coordinates[0].address + ' ' +
                    coordinates[0].city + ' ' +  coordinates[0].state + '</b></div>';
                marker.addAutoExpand(txt);
                _map.addOverlay(marker);
                _map.drawZoomAndCenter(centerPoint);
            } else if (typeof GLatLng != 'undefined' &&
                       jmaki.widgets.google &&
                       jmaki.widgets.google.map &&
                       jmaki.widgets.google.map.Widget &&
                       jmaki.attributes.get(keys[l]) instanceof jmaki.widgets.google.map.Widget) {
                // set the google map
                var _map = jmaki.attributes.get(keys[l]).map;
                var centerPoint = new GLatLng(coordinates[0].latitude,coordinates[0].longitude);
                _map.setCenter(centerPoint);
                var marker = new GMarker(centerPoint);
                _map.addOverlay(marker);
                var txt = '<div style="width:160px;height:50px;"><b>' + coordinates[0].address + ' ' +
                    coordinates[0].city + ' ' +  coordinates[0].state + '</b></div>';
                marker.openInfoWindowHtml(txt);              
            }
        }
}
// add listerner mapping for geocoder
jmaki.addGlueListener(new RegExp("/jmaki/plotmap$"), "jmaki.listeners.geocoderListener");
// add listerner mapping for backward compatibility
jmaki.addGlueListener(new RegExp("/yahoo/geocoder$"), "jmaki.listeners.geocoderListener");


// sytem level filters
jmaki.namespace("jmaki.filters");

// convert an rss feed to the jMaki table format
jmaki.filters.tableFilter = function(input) {

    var _columns = [
            {title: 'Title'},
            //{title: 'URL'},
            {title: 'Date'},
            {title: 'Description'}
            ];
    var _rows = [];

    for (var _i=0; _i < input.channel.items.length;_i++) {
      var row = [
         input.channel.items[_i].title,
        // input.channel.items[_i].link,
         input.channel.items[_i].date,
         input.channel.items[_i].description
      ];
      _rows.push(row);
    }
    return {columns : _columns, rows : _rows};
}

// convert an rss feed to the jMaki accordion format
jmaki.filters.accordionFilter = function(input) {

    var _rows = [];

    for (var _i=0; _i < input.channel.items.length;_i++) {
      var row = {
         label : input.channel.items[_i].title,
        // input.channel.items[_i].link,
        // input.channel.items[_i].date,
        content : input.channel.items[_i].description
      }
      _rows.push(row);
    }
    jmaki.log("rows count=" + _rows.length);
    return {rows : _rows};
}
system-glue.js

                                                                                                                        return to top of the exercise

Solution


The solution is provided as a ready-to-open-and-build NetBeans project as <LAB_UNZIPPED_DIRECTORY>/ajaxjmakimashup/samples/CityLocator.


Summary

In this exercise,  you have built and run a couple of sample applications using various jMaki widgets that are available from jMaki NetBeans plug-in.  You also tried different CSS layouts.

                                                                                                                        return to the top




Exercise 3: Build Craig's List Mashup application

In this exercise, you are going to build a mashup application in which Craig's list and Yahoo map is mashed up.

  1. Open and build "jmaki-cl-mashup" project
  2. Analyze the application

(3.1) Open and build "jmaki-cl-mashup" project


1. Select File->Open Project (Ctrl+Shift+O). The Open Project dialog box appears.
2. Browse down to <LAB_UNZIPPED_DIRECTORY>/ajaxjmakimashup/samples directory.
3. Select jmako-cl-mashup.
4. Click Open Project Folder. (Figure-1.10 below)  The jmaki-cl-mashup project node appears under Projects tab window of NetBeans.

5. Right click jmaki-cl-mashup project node and select Run. (Figure-3.11 below)


Figure-3.11: Run the application

6. Obeserve that the browser gets displayed.  (Figure-3.12 below)

Figure-3.12: CraigList Mashup application

Figure-3.13: CraigList Mashup application

(3.2) Analyze the code


1. index.jsp
<%@ taglib prefix="a" uri="http://jmaki/v1.0/jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<link rel="stylesheet" href="jmaki-2column-footer.css" type="text/css"></link>


<html>
    <head>
        <title>jMaki CraigsList Mashup Sample</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
      <style type="text/css">
     .logo { background: url(images/jmaki-seal.png) top right;width:100px; height:80px;margin-top:0px;background-repeat: no-repeat }
    </style>
    <!--[if lt IE 7]>
        <style type="text/css">
            .logo { background: none; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=image src=images/jmaki-seal.png);cursor:pointer }
        </style>
    <![endif]-->
    </head>
    <body>
        <div class="border">
           
            <div class="header">
                <div class="banner"><div class="logo" style="float:left"></div>
                <div style="margin-top:20px; float:left;">jMaki CraigsList Mashup Sample</div>
                </div>
               
                <div class="subheader">
                    <div>
                        <a href="mailto:feedback@youraddress">Feedback</a> |
                        <a href="#">Site Map</a> |
                        <a href="#">Home</a>
                    </div>
                </div> <!-- sub-header  -->
            </div> <!-- header -->

            <div class="main">
                <div class="rightColumn" style="height:400px">
                      <a:widget  name="yahoo.map"
                               args="{ centerLat : 37.4041960114344,
                               centerLon : -122.008194923401 }" />
                                 

                   
                </div> <!-- end leftColumn -->
       
                <div class="leftColumn" style="height:400px">
                    <a:widget name="dojo.table"
                            args="{filter : 'jmaki.filters.clTableFilter'}"
                            service="/xhp?key=cl" />

                </div> <!-- leftColumn -->
              

            </div> <!-- main -->
            <div class="footer">Data Provided by <a href="http://www.craigslist.org">Craigs List</a>, Maps Provided by <a href="http://www.yahoo.com">Yahoo</a> /
            <a href="http://www.google.com">Google</a>, Geocoder by <a href="http://www.yahoo.com">Yahoo</a>, and Filter Table provided by the <a href="http://www.dojotoolkit.org">Dojo Toolkit<a/>.</div>
        </div> <!-- border -->
    </body>
</html>
Code-3.21: index.jsp

{"xhp": {
    "version": "1.1",   
    "services": [
        {"id": "cl",
         "url":"http://sfbay.craigslist.org/sby/rfs/index.rss",
         "xslStyleSheet": "rss.xsl"
        },   
        {"id": "yahoogeocoder",
         "url":"http://api.local.yahoo.com/MapsService/V1/geocode",
         "apikey" : "appid=jmaki-key",
         "xslStyleSheet": "yahoo-geocoder.xsl",
         "defaultURLParams": "location=santa+clara,+ca"
        }
    ]
  }
}
Code-3.22: xhp.json

3. glue.js

jmaki.namespace("jmaki.listeners");
         
jmaki.listeners.mapLocation = function(loc) {
       var location = "location="+ loc + ",ca";
       dojo.io.bind({
           url: jmaki.xhp + "?key=yahoogeocoder&urlparams=" + encodeURIComponent(location),
           method: "get",
           mimetype: "text/json",
           load : function(type, data) {
               jmaki.publish("/jmaki/plotmap", data.coordinates);
           }
       });
}
// add listerner mapping for geocoder
jmaki.addGlueListener("/jmaki/mapLocation", "jmaki.listeners.mapLocation");

jmaki.namespace("jmaki.filters");

// convert an rss feed to the jMaki table format
jmaki.filters.clTableFilter = function(input) {
    var _columns = [
            {title: 'Title'},
            {title: 'City'},           
            {title: 'Price'}
            ];
    var _rows = [];
    // parse each title to get the name, city, and price
    // title contains description (city / district | neighborhood) $00000   
    for (var _i=0; _i < input.channel.items.length;_i++) {
      var _link = input.channel.items[_i].link;     
      var _title = input.channel.items[_i].title;
      var _name = "";
      var cityStart = _title.lastIndexOf("(");
      if (cityStart != -1) _name = _title.substring(0, cityStart);
      var cityEnd = _title.indexOf(")", cityStart);
      var _city = "";
      if (cityStart != -1 && cityEnd != -1) {
          _city = _title.substring(cityStart + 1, cityEnd);
          // get rid of downtown north south east and west
          _city = _city.replace("downtown", "").replace("north", "");
          _city = _city.replace("south", "").replace("east", "");
          _city = _city.replace("west", "");
          // only go for the city when district is mentioned
          if (_city.indexOf("/") != -1) _city = _city.substring(0, _city.indexOf("/") -1);
      }
      // create a link that will publish and event to map the city
      var _cityLink = "<a href=\"javascript:jmaki.publish('/jmaki/mapLocation','" +
                _city + "');\">" + _city + "</a>";
      var _nameLink = "<a href=\"" + _link + "\" target=\"external\">" + _name + "</a>";               
      var _date = input.channel.items[_i].date;
      var _price = /\$[0-9]*/.exec(_title);
      var row = [
         _nameLink,
         _cityLink,
         _price
      ];
      _rows.push(row);
    }
    return {columns : _columns, rows : _rows};
}
Code-3.24: glue.js


Summary


In this exercise, you have learned how to mashup Craig's list and Yahoo map.

                                                                                                                        return to the top

 


Exercise 4: Creating Mashups with jMaki - A real-life RIA using jMaki

This exercise is based on Arun Gupta's Creating Mashups with jMaki - A real-life RIA using jMaki (Sun Tech Days Event Map) screencast blog.

(4.1) Create a new project

















create table TECHDAYS_SCHEDULE (startDate date,
 endDate date,
 location varchar(255),
 PRIMARY KEY (startDate, endDate))

INSERT INTO TECHDAYS_SCHEDULE VALUES ('9/11/2007', '9/12/2007', 'Boston, United States');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('9/24/2007', '9/25/2007', 'Rome, Italy');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('9/26/2007', '9/28/2007', 'Milan, Italy');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('10/19/2007', '10/19/2007', 'Taipei, Taiwan');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('10/23/2007', '10/25/2007', 'Shanghai, China');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('11/1/2007', '11/3/2007', 'Beijing, China');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('11/6/2007', '11/8/2007', 'Tokyo, Japan');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('12/3/2007', '12/5/2007', 'Frankfurt, Germany');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('1/9/2008', '1/10/2008', 'Atlanta, United States');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('2/27/2008', '2/29/2008', 'Bangalore, India');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('3/4/2008', '3/6/2008', 'Sydney, Australia');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('3/11/2008', '3/13/2008', 'Johannesburg, South Africa');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('4/1/2008', '4/1/2008', 'St Petersburg, Russia');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('4/1/2008', '5/1/2008', 'Manila, Philippines');
INSERT INTO TECHDAYS_SCHEDULE VALUES ('5/21/2008', '5/23/2008', 'Mexico City, Mexico');














@NamedQueries({@NamedQuery(name = "TechdaysSchedule.findAll", query = "SELECT t FROM TechdaysSchedule t"),










<%@ page import="java.util.*" %>
<%@ page import="suntechdays.TechdaysSchedule" %>
<%@ page import="javax.persistence.*" %>
<%
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("jmaki-suntechdaysPU");
            EntityManager em = emf.createEntityManager();
            List list = em.createNamedQuery("TechdaysSchedule.findAll").getResultList();
            out.println("{columns : [" +
                    "{ label : 'City', id : 'city'}," +
                    "{ label :'Start Date', id : 'startdate'}," +
                    "{ label :'End Date', id : 'enddate'}" +
                    "],");
            out.println("rows: [");
            for (int i = 0; i < list.size() - 1; i++) {
                TechdaysSchedule techdays = (TechdaysSchedule) list.get(i);
                out.print("{ id: '" + techdays.getLocation() + "', " +
                        "city: '" + techdays.getLocation() + "'," +
                        "startdate: '" + techdays.getTechdaysSchedulePK().getStartdate() + "'," +
                        "enddate: '" + techdays.getTechdaysSchedulePK().getEnddate() + "'}");
                if (i < list.size() - 1) {
                    out.println(",");
                } else {
                    out.println();
                }
            }
            out.println("] }");
%>









Solution


The solution is provided as a ready-to-open-and-build NetBeans project as <LAB_UNZIPPED_DIRECTORY>/ajaxjmakimashup/samples/jmaki_suntechdays.

Summary

In this exercise, you learned how to use JPA as a backend service.

  
                                                                                                                                   Return to the top



Exercise 5: Creating Mashups with jMaki - A real-life RIA using jMaki

This exercise is based on Arun Gupta's Creating Mashups with jMaki - A real-life RIA using jMaki (Sun Tech Days Event Map) screencast blog.




@NamedQuery(name = "TechdaysSchedule.findByMonth",query = "SELECT t FROM TechdaysSchedule t WHERE t.techdaysSchedulePK.startdate >= :firstdate and t.techdaysSchedulePK.enddate <= :lastdate"),

<%@ page import="java.util.*" %>
<%@ page import="suntechdays.*" %>
<%@ page import="javax.persistence.*" %>
<%@ page import="java.text.SimpleDateFormat" %>

<%
            String dateParam = request.getParameter("date");
            Date date = null;
            if (dateParam == null || "".equals(dateParam)) {
                date = Calendar.getInstance().getTime();
            } else {
                SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/yyyy");
                date = sdf.parse(dateParam);
            }
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("jmaki-suntechdaysmapPU");
            EntityManager em = emf.createEntityManager();
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.set(Calendar.DATE, 1);
            Date firstDateOfMonth = cal.getTime();

            cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
            Date lastDateOfMonth = cal.getTime();

            List<TechdaysSchedule> list = em.createNamedQuery("TechdaysSchedule.findByMonth").
                    setParameter("firstdate", firstDateOfMonth).
                    setParameter("lastdate", lastDateOfMonth).
                    getResultList();
            out.println("[");

            boolean first = true;
            int count = 0;
            SimpleDateFormat sdf = new SimpleDateFormat("MMM d, yyyy");
            for (TechdaysSchedule t : list) {
                StringBuffer buf = new StringBuffer();
                buf.append(sdf.format(t.getTechdaysSchedulePK().getStartdate()));
                buf.append(" - ");
                buf.append(sdf.format(t.getTechdaysSchedulePK().getEnddate()));

                String city = t.getLocation() + ", (" + buf.toString() + ")";
                out.println("{");
                out.println("name: \"" + t.getLocation() + "\", ");
                out.println("label: \"" + city + "\", ");
                out.println("value: \"" + city + "\"");
                if (first) {
                    out.println(", selected: " + true);
                    first = false;
                }

                out.println("}");
                if (count++ < list.size() - 1) {
                    out.println(",");
                }
            }
            out.println("]");
%>

Solution


The solution is provided as a ready-to-open-and-build NetBeans project as <LAB_UNZIPPED_DIRECTORY>/ajaxjmakimashup/samples/jmaki_suntechdays.

Summary

In this exercise, you learned how to use JPA as a backend service.



  
                                                                                                                                   Return to the top




Homework_Exercise(For people who are taking Sang Shin's "AJAX online course")


<to be provided>