Skip to main content

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

Posted by arungupta on September 11, 2007 at 7:34 AM PDT

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

Related Topics >>