Arun Gupta, Miles to go ...

Arun Gupta is a technology enthusiast, a passionate runner, and a community guy who works for Sun Microsystems.
« Previous day (Sep 10, 2007) | Main | Next day (Sep 12, 2007) »

http://blogs.sun.com/arungupta/date/20070911 Tuesday September 11, 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

del.icio.us | furl | simpy | slashdot | technorati | digg |
|
« Previous day (Sep 10, 2007) | Main | Next day (Sep 12, 2007) »

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.