Monday Dec 31, 2007

Screencast #Web11: Travel Map - Another Real-life app using jMaki & Jersey

In my role of Technology Evangelist, I get the opportunity to meet a lot of community (folks like you :) all around the world. In the year 2007, I represented GlassFish (and related technologies - Metro, jMaki and Jersey) at multiple conferences. This blog introduces a  new real-life application that plots all the places I visited this year on a jMaki-wrapped Google Map widget. Clicking on the marker shows more information about the event such as dates and the blog entry covering the event.

Play the video below to see how the application looks like.

Here is the architecture of this application:

travel map architecture

It consists of a server-side and a client-side applications - developed as NetBeans projects.

  1. Server-side project - A RESTful Web service endpoint that provides resource represenations for all the events attended and associated meta information such as date and blog URLs. This endpoint is created using Jersey.
  2. Client-side project - A jMaki-enabled Web application that consumes the representations generated by the RESTful Web service and plots the information on a jMaki-wrapped Google Map widget.

Both the server-side and client-side are deployed on GlassFish.

This is only a sample application so optimizations are certainly possible and corner cases (such as no blog entry for a particular visit) are not accounted for. But the application still demonstrates the concept. The fully built application looks like as shown below:

Arun's Travel Map 2007

My first presentation in this role was Sun Tech Days Atlanta (highlighted in the image). This application generates an interactive Google Map so feel free to zoom in/out and click 

And one last thing before we build the application. Here is the list of technologies and associated concepts used to build this application:

  1. Jersey
    1. Shows an example of how RESTful Web services can be easily generated from JPA Entity Classes.
    2. Shows how all the resource representations (instead of reference to individual resources) can be returned by a Jersey endpoint.
  2. jMaki
    1. Shows how to consume XML data from an external service (RESTful Web service endpoint) in this case.
    2. Shows how the underlying data model of a widget (Google Map in this case) can be accessed and manipulated.
  3. GlassFish
    1. All the applications are deployed on GlassFish - implicit in the development/deplyment process through seamless integration with NetBeans.
  4. NetBeans 6
    1. Used for generation of RESTful Web services from JPA Entity Classes.
    2. Used for generating/deploying jMaki projects and drag-and-drop of jMaki-wrapped widgets.
  5. JavaScript Closures - to persist the state for asynchronous callback functions
  6. JavaScript DOM processing - to process the XML data received from Jersey endpoint.
  7. Google Maps API
    1. Generate meaningful markers on each location
    2. Populate Google Map from a RESTful Web service endpoint
  8. Java Persistence API - to retrieve data from the database.

And finally, lets build this application. Lets build the RESTful Web service endpoint project first.

  1. Create and Populate the Database
    1. In the NetBeans IDE, go to Services tab, and connect to the database with URL "jdbc:derby://localhost:1527/sample [app on APP]" (right-click and select "Connect...").
    2. Right-click on this database and select "Execute Command..." and create a table by giving the following command:

      create table EVENTS (id int GENERATED ALWAYS AS IDENTITY,
                          event_name varchar(255),
                          dates varchar(20),
                          venue varchar(255),
                          blogs varchar(2056),
                          PRIMARY KEY (id))


      Notice, the "id" column is marked as IDENTITY that instructs the database to auto generate the values for this column and increment by 1 (default) for each row. This column is also marked as the primary key.
    3. Again right-click on the database and select "Execute Command..." to add data to the table by giving the following command:

      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('SunTech Days - Atlanta', 'Jan 16 - Jan 17', 'Cobb Galleria Center, Two Galleria Parkway, Atlanta, Georgia, 30339', 'http://blogs.sun.com/arungupta/entry/wsit_and_web_2_0');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('jMaki Day', ' Feb 23', '4150 Network Circle Santa Clara, CA 95054', 'http://blogs.sun.com/arungupta/entry/sun_internal_jmaki_day_review');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Ajax World - New York', 'Mar 19 - Mar 21', 'The Roosevelt Hotel, 45 E 45th St, New York, NY 10017', 'http://blogs.sun.com/arungupta/entry/sun_ajax_world');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('The Server Side Java Symposium - Las Vegas', 'Mar 22', '3355 Las Vegas Blvd. South Las Vegas, NV 89109', 'http://blogs.sun.com/arungupta/entry/sun_the_server_side_java, http://blogs.sun.com/arungupta/entry/tango_at_venetian_las_vegas');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('JavaOne - San Francisco', 'May 7 - May 11', 'Moscone Center, 747 Howard Street, San Francisco, CA 94103', 'http://blogs.sun.com/arungupta/entry/slides_for_ts_4865, http://blogs.sun.com/arungupta/entry/javaone_2007_day_1_finished, http://blogs.sun.com/arungupta/entry/javaone_2007_day_1, http://blogs.sun.com/arungupta/entry/javascript_everywhere_javaone_2007_demo, http://blogs.sun.com/arungupta/entry/excel_using_wsit_javaone_2007, http://blogs.sun.com/arungupta/entry/ts_4865_takes_two_to, http://blogs.sun.com/arungupta/entry/communityone_glassfish_day_report, http://blogs.sun.com/arungupta/entry/javaone_2007_backstage, http://blogs.sun.com/arungupta/entry/javaone_2007_is_almost_here, http://blogs.sun.com/arungupta/entry/my_javaone_2007_picks');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rails Conf - Portland', 'May 17 - May 20', '777 NE MLK, Jr. Blvd. Portland, OR 97232', 'http://blogs.sun.com/arungupta/entry/tim_bray_s_keynote_session, http://blogs.sun.com/arungupta/entry/sun_rails_conf_2007_keep, http://blogs.sun.com/arungupta/entry/getting_started_with_jruby_tutorial, http://blogs.sun.com/arungupta/entry/jmaki_netbeans_and_glassfish_in');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Google Developer Day - San Jose', 'May 31', '150 W San Carlos St San Jose, CA 95113', 'http://blogs.sun.com/arungupta/entry/google_developer_day_report');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mashup Camp - Mountain View', 'Jul 18 - Jul 19', 'Computer History Museum, 1401 N Shoreline Blvd., Mountain View, CA 94043', 'http://blogs.sun.com/arungupta/entry/jmaki_at_mashup_camp_report, http://blogs.sun.com/arungupta/entry/jmaki_mashup_camp');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('OSCON - Portland', 'Jul 23 - Jul 27', '777 NE MLK, Jr. Blvd. Portland, OR 97232', 'http://blogs.sun.com/arungupta/entry/jmaki_oscon');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('JRuby Hack Day - San Francisco', 'Aug 8', '1201 8th St, San Francisco, CA 94107', 'http://blogs.sun.com/arungupta/entry/jruby_on_rails_hackday_report, http://blogs.sun.com/arungupta/entry/learn_jruby_on_rails_free');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rich Web Experience - San Jose', 'Sep 6 - Sep 8', '170 S Market St, San Jose, CA 95113', 'http://blogs.sun.com/arungupta/entry/the_rich_web_experience_2007, http://blogs.sun.com/arungupta/entry/jmaki_javafx_the_rich_web');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rails Conf Europe - Berlin', 'Sep 17 - Sep 19', 'Maritim Pro Arte, Friedrichstrasse 151, 10117 Berlin', 'http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day2, http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day1, http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day, http://blogs.sun.com/arungupta/entry/jmaki_netbeans_and_glassfish_in1');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days - Rome', 'Sep 24 - Sep 25', 'Meliá Roma Aurelia Antica, Vía Aldobrandeschi, 223  Rome ITALY  00163', 'http://blogs.sun.com/arungupta/entry/netbeans_day_rome_2007, http://blogs.sun.com/arungupta/entry/travel_tips_to_rome, http://blogs.sun.com/arungupta/entry/glassfish_metro_jersey_and_jmaki');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days - Milan', 'Sep 26 - Sep 28', 'ATA Hotel Quark - Via Lampedusa 11/a 20141 Milano, Italia', 'http://blogs.sun.com/arungupta/entry/glassfish_day_milan_2007');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mid West Java Tech Days - Minneapolis', 'Oct 16', 'University of St Thomas, MPL 201, 1000 LaSalle Avenue, Minneapolis, MN 55403-2005', 'http://blogs.sun.com/arungupta/entry/mid_west_java_tech_days, http://blogs.sun.com/arungupta/entry/metro_and_jmaki_in_minneapolis');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mid West Java Tech Days - Chicago', 'Oct 18', 'Donald E Stephens Convention Center, 9301, W Bryn Mawr Ave, Rosemont IL 60018', 'http://blogs.sun.com/arungupta/entry/mid_west_java_tech_days1, http://blogs.sun.com/arungupta/entry/crowne_plaza_chicago_o_hare, http://blogs.sun.com/arungupta/entry/metro_and_jmaki_in_minneapolis');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Silicon Valley Code Camp - Los Altos', 'Oct 27', 'Foothill College, Los Altos, CA', 'http://blogs.sun.com/arungupta/entry/silicon_valley_code_camp_trip, http://blogs.sun.com/arungupta/entry/metro_jmaki_silicon_valley_code');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days - Beijing', 'Nov 1 - Nov 3', 'Beijing International Convention Center, No.8 Beichendong Road Chaoyang District, Beijing', 'http://blogs.sun.com/arungupta/entry/glassfish_day_beijing_2007_by, http://blogs.sun.com/arungupta/entry/wangfujing_street_authentic_china_in, http://blogs.sun.com/arungupta/entry/sun_tech_days_beijing_talent, http://blogs.sun.com/arungupta/entry/sun_tech_days_beijing_day, http://blogs.sun.com/arungupta/entry/travel_tips_to_beijing, http://blogs.sun.com/arungupta/entry/glassfish_day_beijing');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - Toronto', 'Nov 21', 'Toronto City Center', 'http://blogs.sun.com/arungupta/entry/metro_jmaki_jruby_glassfish_q');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - Montreal', 'Nov 21', 'Montreal City Center', 'http://blogs.sun.com/arungupta/entry/metro_jmaki_jruby_glassfish_q');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('GlassFish - Delhi University', 'Dec 3', 'New Delhi', 'http://blogs.sun.com/arungupta/entry/glassfish_delhi_university');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('FOSS.IN - Bangalore', 'Dec 4', 'India Institute of Science, Bangalore', 'http://blogs.sun.com/arungupta/entry/packaging_java_apps_for_ubuntu, http://blogs.sun.com/arungupta/entry/foss_in_schedules_now_available, http://blogs.sun.com/arungupta/entry/glassfish_foss_in_2007');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - Bangalore', 'Dec 4', 'Bangalore', 'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - Chennai', 'Dec 5', 'Chennai', 'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - Pune', 'Dec 6', 'Pune', 'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
      INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner Preso - San Francisco', 'Dec 17', 'San Francisco', 'http://blogs.sun.com/arungupta/');

      These SQL statements populate the database with details about my visits in 2007. If you'd like to develop a similar application highlighting your visits then you'll need to modify the VALUES clause to match accordingly.
  2. Create and Configure RESTful Web service endpoint
    1. Create a Persistence Unit as described in "Generating Entity Classes from Database" section in Getting Started with RESTful Web Services. Lets say the project name is "WebApplication3", package name is "events" and the table name to generate Entity classes is EVENTS. Take everything else as the defaults.
    2. Generate a RESTful Web service as described in "Generating RESTful Web Services from Entity Classes" section in Getting Started with RESTful Web Services.
      1. Add a new class EventsList in the events package as:

        @javax.xml.bind.annotation.XmlRootElement
        public class EventsList {
          @javax.xml.bind.annotation.XmlElement
          protected java.util.List<Events> events;

          public EventsList() {
            if (events == null)
              events = new java.util.ArrayList<Events>();
          }

          public void add(Events name) {
            events.add(name);
          }

          public java.util.List<Events> getValue() {
            return events;
          }
        }
      2. In service.EventsResource, change the method associated with GET to:

        public EventsList get() {
                EventsList eventsList = new EventsList();
                List<Events> list  = PersistenceService.getInstance().createQuery("SELECT e FROM Events e").getResultList();
                for (Events e : list) {
                    eventsList.add(e);
                }
                return eventsList;
        }

        This will ensure that all the resource representations are returned instead of a reference to the resource. Make sure to fix the imports.
That's it, our server-side project is now ready. "http://localhost:8080/WebApplication3/resources/events" now return a complete RESTful representation of all the rows from the database table EVENTS.

Lets build the client-side application next. Make sure jMaki plug-in in NetBeans IDE is already installed.
  1. In the NetBeans IDE, create a new Web project, enable "Ajax Framework" and choose the "Standard" layout for "index.jsp".  Lets say the project name is "WebApplication4".
  2. Drag-and-drop a jMaki-wrapped Google Map widget in the 'Main Content Area' and jMaki-wrapped Yahoo Button in the 'Sidebar Content Here'.
  3. Customise the widgets
    1. Add id="mymap" attribute to the Google Map widget. The updated widget looks like as shown below:

      <a:widget  name="google.map" id="mymap"
               args="{ centerLat : 37.4041960114344,
                       centerLon : -122.008194923401 }" />

      id="mymap"
      will allow the Map widget to be accessed by name later.
    2. Add args="{label:'Plot Events'}" attribute to thes Yahoo button widget. The updated widget looks like as shown below:

      <a:widget name="yahoo.button" args="{label:'Plot Events'}"/>
  4. In glue,js, add the following code to \*onClick subscribe method:

    var url = jmaki.xhp + "?id=events";
    var _map = jmaki.getWidget("mymap").map;
    _map.setZoom(2);
    _map.clearOverlays();
    _map.enableInfoWindow();
       
    jmaki.doAjax({method: "GET",
        url: url,
        callback: function(_req) {          
            var xmlobject = (new DOMParser()).parseFromString(_req.responseText, "text/xml");
            var root = xmlobject.getElementsByTagName('eventsList')[0];
            var events = root.getElementsByTagName('events');
            for (var i = 0 ; i < events.length ; i++) {
                var event = events[i];
                var eventName = event.getElementsByTagName('eventName')[0].firstChild.nodeValue;
                var venue = event.getElementsByTagName('venue')[0].firstChild.nodeValue;
                var blogs = event.getElementsByTagName('blogs')[0].firstChild.nodeValue;
                var dates = event.getElementsByTagName('dates')[0].firstChild.nodeValue;
               
    var id = event.getElementsByTagName('id')[0].firstChild.nodeValue;
                   
                var encodedLocation = encodeURIComponent("location=" + venue);
                var url = jmaki.xhp + "?id=yahoogeocoder&urlparams=" + encodedLocation;
                jmaki.myHandler(url, eventName, blogs, dates, id, _map);
            }
        }
    });
  5. Add the following functions above the \*onClick subscribe method:

    // "Function closure" used from http://econym.googlepages.com/basic1.htm
    // Creates local copy of "marker" and "html" variables to be preserved for later use
    function createMarker(point,html) {
        var marker = new GMarker(point);
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(html);
        });
        return marker;
    };

    // Function closure that preserves "eventName", "blogs", "dates and "id"
    // Gets the latitude/longitude from Yahoo Geocoding service and plots them on the map
    // Also creates meaningful markers
    jmaki.myHandler = function(_url, eventName, blogs, dates, id, _map) {
        jmaki.doAjax({url: _url,
            callback : function(req) {
                if (req.responseText.length > 0) {
                    jmaki.log("name: " + eventName);
                    var response = eval("(" + req.responseText + ")");
                    var coordinates = response.coordinates;
                    jmaki.publish("/jmaki/plotmap", coordinates);
                    jmaki.log("plotting " + eventName);
                    var latlng = new GLatLng(coordinates[0].latitude, coordinates[0].longitude);
                   
                    var blogHtml = "";
                    b = blogs.split(', ');
                    for (i=0; i<b.length; i++) {
                        blogHtml += '<a href="' + b[i] + '">' + (i+1) + '</a>';
                        if (i<b.length-1)
                            blogHtml += ", ";
                    }
                   
                    var txt = '<table>' +
                    '<tr><td>#' + id + ": " + eventName + '</td></tr>' +
                    '<tr>Dates: ' + dates + ', 2007</td></tr>' +
                    '<tr><td>Blogs: ' + blogHtml + '</td></tr>' +
                    '</table>';
                   
                    var marker = createMarker(latlng, txt);
                    _map.addOverlay(marker);
                    marker.openInfoWindowHtml(txt);
                } else {
                    jmaki.log("Failed to get coordinates for " + location );
                }
            }
        });   
    };
  6. Add the following entry in Web Pages, resources, xhp.json:

    ,
    {"id": "events",
     "url":"http://localhost:8080/WebApplication3/resources/events/"
    }


    assuming WebApplication3 is the project where RESTful Web service endpoint is hosted.
That completes our client-side web application as well. Now, either hit F6 (default key to Run the NetBeans project) and this will show http://localhost:8080/WebApplication4/index.jsp in the configured browser. Once you click on "Plot Events" button, all the markers on the Google Map are plotted.
Future Improvements
  1. If Jersey can return all the resource representations directly, then the workaround used above may not be required.
  2. Use e4x after <script type="text/javascript"> in index.jsp can be generated as <script type="text/javascript; e4x=1">.
  3. Build the client-side application using Rails once issue #309 & #310 are resolved.
    1. Once deployed as Rails application on WEBrick, create a WAR file and deploy on GlassFish.
    2. Try this application using GlassFish v3 gem.
  4. Embed Google Map in the blog entry.
An alternate title of this blog entry could've been "How I spent my winter break ?". But in order to keep the title inline with rest of other entries (keeping it simple and reflecting the content of the entry) I decided to use the existing title ;-)

Technorati: screencast conf jmaki jersey netbeans glassfish jpa javascript googlemaps restful web2.0 jmakimashups

Thursday Dec 13, 2007

Screencast #WS8: Tango with NetBeans 6

David Coldrick recorded a screencast for Australian Developer Days. The demo shows how NetBeans 6 allow Web services to be easily created and deployed on GlassFish.

It is similar to screencast #ws7 but good to see somebody else creating these videos :)

Technorati: screencast glassfish webservices metro tango netbeans

Wednesday Nov 07, 2007

Screencast #Web10: CRUD using jMaki and JPA

This screencast shows how to create a simple jMaki application, using NetBeans IDE, that performs some of the CRUD operations on a Data Table widget. It uses Java Persistence API (JPA) to connect to the database and the application is deployed on GlassFish. The rest of the CRUD operations can be easily built using the same methodology.

The steps followed in this screencast are also described in detail.

Enjoy it here!

Technorati: screencast jmaki netbeans glassfish jpa database crud

Thursday Oct 04, 2007

Screencast #Web 9: JRuby-on-Rails standalone and shared WARs in GlassFish

Are you an existing GlassFish V2 user and interested in using Rails applications ? - JRuby module is now available on the Update Center. This module allows you to create standalone or shared WAR of a Rails application that can be easily deployed on GlassFish. Read the complete details here.

A screencast following these steps is available here.

A comprehensive list of JRuby on GlassFish documentation is available here.

Technorati: rubyonrails jruby glassfish updatecenter jrubyonglassfish screencast ruby

Wednesday Oct 03, 2007

Screencast #WS7: Secure and Reliable Web service using Metro/GlassFish and NetBeans IDE 6

The Web services support in NetBeans 6 is further simplified from NetBeans 5.5.1. There are two main points I like:

  • Integral support for Security, Reliability and Transactions on an endpoint. This means there is no need to download any additional plug-in.
  • A new Web Services Designer allows to design the Web service visually. This lowers the entry barrier for first-time users.

There are other minor enhancements as well which makes the overall experience much more pleasant. This screencast shows how a Secure and Reliable Web service can be easily developed using NetBeans 6 and deployed on Metro/GlassFish.

A cutting edge build of NetBeans 6 can be downloaded from here or a more stable build (beta 1 as of today) from here. GlassFish V2 Final is bundled with both NetBeans beta1 and daily build.

Enjoy it here!

Technorati: screencast webservices metro glassfish netbeans

Sunday Sep 16, 2007

Screencast #Web8: jMaki on Rails for Dummies - 2nd edition

The support for Rails in NetBeans IDE has improved considerably in the past few days. Greg and Ludo have been working on ramping up the jMaki NetBeans module as well. This screencast is an update to #web2 and shows how the development experience for creating a jMaki-enabled Rails application is drastically simplified.

The screencast shows how a jMaki-wrapped Yahoo and Dojo DataTable widget can be used to pull data from MySQL database using ActiveRecord in a Rails application. The screencast also shows how multiple widgets on a RHTML View can talk to each other using simple tags.

Enjoy it here!

Technorati: screencast jmaki netbeans rubyonrails mysql

Monday Sep 10, 2007

Screencast #Web7: Creating Mashups with jMaki - A real-life RIA using jMaki (Sun Tech Days Event Map)

Sun Microsystems kicks off 2007-2008 Tech Days and marks the 10th anniversary of the developer event. This blog celebrates the decade by announcing "Sun Tech Days Event Map" - a real-life RIA created using jMaki. It allows you to choose the date on a web page using a rich calendar widget, shows the city where Sun Tech Days event is happening during that month and then shows that city location in a map. Play the video below to see how the application looks like:

This application shows several concepts of jMaki:

  1. Widgets from different toolkits (Dojo Combobox, Yahoo Calendar and Google Map in this case) co-located on the same page
  2. Multiple widgets from different toolkits communicate with each other using the publish/subscribe mechanism & Actions (and here)
  3. Populate widgets by accessing services from the backend
  4. Using Java Persistence API to return the data understood by jMaki widgets

This application is built using NetBeans IDE 5.5.1, jMaki 0.9.7.3 and deployed on GlassFish RC4. Let's get started.

  1. In the NetBeans IDE, create a new project
    1. Right-click in Projects window, select "Web" in "Categories" and "Web application" in "Projects". Click on "Next >".
    2. Enter the project name as "SunTechDays" and choose GlassFish as the "Server" and take all other values default. Click on "Next >".
    3. Select "jMaki Ajax Framework" and choose "Two Fixed Right Sidebars" layout.
    4. Click on "Finish".
  2. Add the following widgets in the generated "index.jsp"
    1. Replace "Top Right Column" by dragging-and-dropping "Dojo Combobox".
    2. Replace "Right Column" with "Yahoo Calendar".
    3. Replace "Left Column" with a "Google Map".
  3. Create and populate the database
    1. In the NetBeans IDE, go to "Runtime" tab, expand "Databases", right-select the node with the value "jdbc:derby://localhost:1527/sample" and select "Connect".
    2. Enter both username and password as "app".
    3. Right-select the database and select "Execute Command...". Create the table using the following SQL

      create table TECHDAYS_SCHEDULE (startDate date,
                                      endDate date,
                                      location varchar(255),
                                      PRIMARY KEY (startDate, endDate))
    4. Populate the database for Sun Tech Days 2007-2008 schedule using the following SQL

      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');
  4. Create a Persistence Unit
    1. In the NetBeans IDE, right-select the project, click on "New", "Entity Classes from Database...".
    2. In the "New Entity Classes from Database" dialog window, choose "Data Source" and select "jdbc/sample" value.
    3. All the available tables are shown in "Available Tables". Select "TECHDAYS_SCHEDULE" and click on "Add >".
    4. Click on "Next >".
    5. Enter the package name as "suntech".
    6. Click on "Create Persistence Unit...".
    7. In "Create Persistence Unit..." dialog window take all the default values and click on "Create".
    8. Click on "Finish".
    9. Expand "Configuration Files", open "persistence.xml", click on "Add Class", click "Cancel", click on "Add Class" again and now select "suntech.TechdaysSchedule" and click on "OK".
    10. Expand "Source Packages", "suntech" node and open "TechdaysSchedule.java".
    11. Add the following NamedQuery to the class. Copy/paste the fragment as the first line in "@NamedQueries" annotation.

      @NamedQuery(name = "TechdaysSchedule.findByMonth", query = "SELECT t FROM TechdaysSchedule t WHERE t.techdaysSchedulePK.startdate >= :firstdate and t.techdaysSchedulePK.enddate <= :lastdate"),
  5. Configure the widgets
    1. Expand "Web Pages", open "glue.js" and add the following code at the end of the file:

      jmaki.subscribe("/yahoo/calendar/onSelect", function(args) {
        var newDate;
        if (typeof args.value == "undefined") {
          var tempDate = new Date();
          newDate = (tempDate.getMonth()+1) + "/" + tempDate.getDate() + "/" + tempDate.getFullYear();
        } else {
          var str = "" + args.value;
          newDate = str.split(" ")[1] + "/" + str.split(" ")[2] + "/" + str.split(" ")[3];
        }

        jmaki.doAjax({method: "POST",
            url: "data.jsp?date=" + encodeURIComponent(newDate),
            callback: function(_req) {
              var tmp = _req.responseText;
              var obj = eval("(" + tmp + ")");
              jmaki.log("tmp "+ obj);
              jmaki.publish('/dojo/combobox/setValues', obj);
              // handle any errors
            }
        });
      });

      jmaki.subscribe("/dojo/combobox/onSelect", function(item) {
        var location = item.value.split(',')[0] + ", " + item.value.split(',')[1];
        var start = item.value.indexOf('(');
        var stop = item.value.lastIndexOf(')');
        var encodedLocation = encodeURIComponent("location=" + location);
        // jmaki.xhp is provided as part of jmaki and maps to the XMLHttpProxy
        var url = jmaki.xhp + "?id=yahoogeocoder&urlparams=" + encodedLocation;
        jmaki.doAjax({url: url, callback : function(req) {
          if (req.responseText.length > 0) {
            // convert the response to an object
            var response = eval("(" + req.responseText + ")");
            var coordinates = response.coordinates;
            v = {results:coordinates};
            jmaki.publish("/jmaki/plotmap", coordinates);
          } else {
            jmaki.log("Failed to get coordinates for " + location );
          }
        }
        });
      });
  6. Configure widgets on the page
    1. Change the Dojo Combobox generated fragment with

      <a:widget name="dojo.combobox" service="data.jsp"/>
    2. Right-select the project, select "New" and then "JSP..." using the name "data". Notice, the IDE automatically picks up the file extension.
    3. Replace the generated template code with the following. This code reads a parameter, parses it into a Date, queries the database using the PersistenceUnit created above and return the result in JSON format.

      <%@ page import="java.util.\*" %>
      <%@ page import="suntech.\*" %>
      <%@ 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("SunTechDaysPU");
        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("]");
      %>

And that's it!

Carla and I conceived this application together and Greg and  helped with gluing the widgets.

Here are some potential fun improvements:

  1. Instead of randomly selecting a date and then using it's month for populating the combo box, tap the event published (if any) for changing month in the calendar widget.
  2. The database structure can be manipulated to include hotel information and provide more meaningful information.
  3. The dates may be shown in the bubble displayed in the map.
  4. Restaurant recommendations may be pulled from another service and shown for the event attendees.

Technorati: jmaki netbeans glassfish suntechdays jpa screencast web2.0

Wednesday Aug 08, 2007

Screencast #Web6: First JRuby app in GlassFish

UPDATE: Simplified steps for GlassFish V2 are available here and for V3 here.

Earlier in a three-part series (part1, part2, part3) I showed how a JRuby application can be deployed on GlassFish. This screencast consolidates all the entries together and shows how such an application can be developed and deployed using NetBeans Ruby IDE.

Enjoy it here!

The screencast is divided in four segments:

  • Create a "Hello World" Rails app
  • Deploy this app as WAR in GlassFish
  • In Rails app, read the greeting from MySQL database
  • Deploy this app as WAR in GlassFish

Here are some more useful links

The NetBeans IDE provides a comprehensive support for Ruby code completion, refactoring, debugging, Rails support, support for RHTML files, code templates, unit test execution, shortcuts, and much more. Please post your questions about Ruby support in NetBeans IDE to users@ruby.netbeans.org.

Technorati: jruby ruby rubyonrails glassfish netbeans screencast

Sunday Aug 05, 2007

Screencast #Web5: Creating Mashups with jMaki - Mashing up the Maps

This second screencast of the Creating Mashups with jMaki Series show how jMaki allows to embed and interact with map widgets in your application.

This screencast shows how to creates two mashups - the first one is where a city location is keyed from name and displayed in map widgets from two different toolkits, and the second one shows how to extract data from Craig's List, process it using jMaki filters and then display the relevant information in a map.

The NetBeans IDE is used for tooling and the jMaki-enabled Web application is deployed on GlassFish.

Enjoy it here!

The key message is jMaki + NetBeans IDE + GlassFish provides a complete platform for creating and deploying powerful mashups, quickly and effectively!

Technorati: jmaki mashups netbeans screencast glassfish jmakimashups

Monday Jul 23, 2007

Screencast #Web4: Creating Mashups with jMaki - Display RSS feed in jMaki Widgets

jMaki provide a flexible framework to create mashups very easily. Today, I'm starting a series of screencasts that will focus on this aspect of jMaki.

The first one in the series is a very simple mashup that pulls RSS feed from a blog entry and display it in two different widgets, without any extra effort. The NetBeans IDE is used for tooling and the jMaki-enabled Web application is deployed on GlassFish.

Enjoy it here!

The key message is jMaki + NetBeans IDE + GlassFish provides a complete platform for creating and deploying powerful mashups, quickly and effectively!

Technorati: jmaki mashups netbeans screencast glassfish jmakimashups

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today