Skip to main content

TOTD #10: Consuming JSON and XML representations generated by a Jersey endpoint in a jMaki Table widget

Posted by arungupta on October 3, 2007 at 5:59 AM PDT

A jMaki widget
expects data in JSON format as defined by the
standard data
models
. There are three possible ways to generate the JSON data from a
Jersey endpoint that can be consumed by a jMaki widget:

  1. Return JSON representation of a resource as generated using the
    BadgerFish convention and then
    apply a stylesheet (specified in xhp.json) to convert the
    received data into the JSON format as expected by the jMaki widget. This
    keeps the server code simple but requires a stylesheet to convert from one
    JSON format (defined by BadgerFish convention) to another JSON format (as
    expected by the jMaki widget).
  2. Return XML representation of the resource and then apply a stylesheet
    (specified in xhp.json) to convert the received JSON into the format as
    expected by the jMaki widget. This keeps the server code simple but requires
    a stylesheet to convert from the XML format (defined by JAXB) to JSON format
    (as expected by the jMaki widget).
  3. Return JSON representation as expected by the jMaki widget. This can be
    achieved only using low-level JSON APIs on the server-side and can be
    directly consumed by the jMaki widget.

This TOTD explains 2nd and 3rd bullet. The first bullet can be applied
following the solution proposed in 2nd bullet.

  1. Download and expand the

    latest Jersey download
    .
  2. Download and install
    GlassFish V2.
    This will be required for deploying the jMaki project and using Database
    client and Persistence libraries.
  3. Open "examples/HelloWorld" project in
    NetBeans 6 IDE.
  4. In the NetBeans IDE, Services tab, expand Databases, right-click on the
    node with URL "jdbc:derby://localhost:1527/sample [app on APP]"
    and select Connect. Enter the password as "app" and select "OK".
  5. Configure the database
    1. Right-click again on the URL and select "Execute Command..."
      and issue the command:



      create table BOOKS (title varchar(255), 
                         
      author varchar(255),
                         
      isbn varchar(255),
                         
      description varchar(255),

                         
      PRIMARY KEY (isbn))




      This will create the database table.
    2. Add data to the newly created table using the following command:



      INSERT INTO BOOKS VALUES('Marathon', 'Jeff Galloway', 'ABCDEF', 'The best book 
      on running');
      INSERT INTO BOOKS VALUES('Run a Marathon', 'Duke', '123456', 'How to train for a
      marathon ?');




      You can enter additional rows if you like.
  6. Create the Persistence Unit
    1. In NetBeans IDE, right-click on the project, select "New",
      "Entity Classes from Database...".
    2. Choose the Database Connection with the URL given above.
    3. In the "Available Tables", select "BOOKS"
      and click on "Add >". Click on "Next >".
    4. Click on "Create Persistence Unit...", take all the
      defaults and click on "Create" and then click on "Finish".
    5. Add the following NamedQuery "
      @NamedQuery(name = "Books.findAll", 
      query = "SELECT b FROM Books b")
      " to the generated Books class.
    6. Add the following annotation "@javax.xml.bind.annotation.XmlRootElement"
      to the generated Books class.
  7. Add a new bean representing the array of Books.
    1. Right-click on "com.sun.ws.rest.samples.helloworld"
      package, select "New", "Java Class..." and
      enter the Class Name as "BookList".
    2. Replace the template class with the following code:



      package com.sun.ws.rest.samples.helloworld;



      /**

       * @author Arun Gupta

       */

      @javax.xml.bind.annotation.XmlRootElement

      public class BookList {

        @javax.xml.bind.annotation.XmlElement

        protected java.util.List<Books> book;



        public BookList() {

          if (book == null)

            book = new java.util.ArrayList<Books>();

        }



        public void add(Books name) {

          book.add(name);

        }



        public java.util.List<Books> getValue() {

          return book;

        }

      }
  8. Add a resource that generates the XML and JSON representation to be
    consumed a jMaki-wrapped DataTable widget.
    1. Expand Source Packages, right-click on "com.sun.ws.rest.samples.helloworld.resources",
      select "New", "Java Class..." and enter the
      Class Name as "TableResource".
    2. Replace the generated template class with the following code:



      package com.sun.ws.rest.samples.helloworld.resources;



      import com.sun.ws.rest.samples.helloworld.BookList;

      import com.sun.ws.rest.samples.helloworld.Books;

      import java.util.List;

      import javax.persistence.EntityManager;

      import javax.persistence.EntityManagerFactory;

      import javax.persistence.Persistence;

      import javax.ws.rs.HttpMethod;

      import javax.ws.rs.ProduceMime;

      import javax.ws.rs.UriTemplate;

      import javax.xml.bind.JAXBException;

      import org.codehaus.jettison.json.JSONArray;

      import org.codehaus.jettison.json.JSONException;

      import org.codehaus.jettison.json.JSONObject;



      /**

       * @author Arun Gupta

       */

      @UriTemplate("/table")

      public class TableResource {

        @HttpMethod

        @ProduceMime("application/xml")

        @UriTemplate("/xml")

        public BookList getXML() throws JAXBException {

          BookList booklist = new BookList();

          for (Books b : getBooks()) {

            booklist.add(b);

          }

          return booklist;

        }



        @HttpMethod

        @ProduceMime("application/json")

        @UriTemplate("/json")

        public JSONObject getJSON() throws JSONException {

          JSONObject tableDataModel = new JSONObject();

          String[] labels = { "Title", "Author", "ISBN",
      "Description"};

          JSONArray columns = new JSONArray();

          for (String l : labels) {

            JSONObject item = new JSONObject();

            item.put("label", l).put("id", l);

            columns.put(item);

          }

          tableDataModel.put("columns", columns);



          JSONArray rows = new JSONArray();

          for (Books b : getBooks()) {

          JSONObject item = new JSONObject();

            item.put(labels[0], b.getTitle());

            item.put(labels[1], b.getAuthor());

            item.put(labels[2], b.getIsbn());

            item.put(labels[3], b.getDescription());

            rows.put(item);

          }

          tableDataModel.put("rows", rows);



          return tableDataModel;

        }



        private List<Books> getBooks() {

          EntityManagerFactory emf =
      Persistence.createEntityManagerFactory("HelloWorldPU");

          EntityManager em = emf.createEntityManager();

          List<Books> list =
      em.createNamedQuery("Books.findAll").getResultList();

          return list;

        }

      }




      The getXML() method returns only the table rows data in an
      XML format. This XML representation of the resource is then processed by
      a stylesheet (specified later in the jMaki application) and converted
      into the JSON format as expected by the jMaki widget. The stylesheet
      adds the column information as well. The getJSON() method
      uses low-level JSON APIs to return the data exactly as expected by the
      jMaki widget (including the column information).



      In the case of returning an XML representation we can return the column
      information as well but that would only complicate the code for this
      sample purpose.
  9. Right-click on "com.sun.ws.rest.samples.helloworld", edit "Main.java"
    and change line 42 to use "TableResource" class instead of "HelloWorldResource".
    The updated code looks like:



    HttpHandler handler = ContainerFactory.createContainer(

            HttpHandler.class,

            TableResource.class);




    Fix the import.
  10. Right-click on project, select "Properties", choose "Libraries"
    and add the following JARs by clicking on "Add JAR/Folder"
    button:
    1. "GLASSFISH_HOME/javadb/lib/derbyclient.jar"
    2. "GLASSFISH_HOME/lib/toplink-essentials.jar"
    3. "GLASSFISH_HOME/lib/toplink-essentials-agent.jar"
  11. Right-click on the Project and select "Run".

This concludes developing/configuring/running the Jersey endpoint. Now let's
create a new web application and add a jMaki widget that consumes the resource
representation exposed by this endpoint:

  1. In the NetBeans IDE, create a new Web application project. Make sure to
    install

    jMaki plugin
    in the NetBeans IDE. Enable "jMaki Ajax Framework"
    for the project.
  2. Expand "Web pages", "resources", and edit "xhp.json"
    to add the following entries at the end:



    ,

    {"id": "jersey-json",

     "url":"http://localhost:9998/table/json"

    },

    {"id": "jersey-xml",

     "url":"http://localhost:9998/table/xml",

     "xslStyleSheet": "table.xsl"

    }




    This defines two external services (Jersey endpoints) that can be used by
    the jMaki widgets. The first entry is a Jersey endpoint that returns JSON
    representation of the resource. The second entry is a Jersey endpoint that
    returns the XML representation and additionally specifies a stylesheet that
    converts the data from XML format to the JSON format expected by the jMaki
    widget.
  3. Expand "Web pages", "resources", "xsl"
    and add a new stylesheet (table.xsl). The content of the stylesheet are given below:



    <?xml version="1.0" encoding="UTF-8" ?>

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" encoding="utf-8"/>



      <xsl:template match="/">

        <xsl:apply-templates select="bookList"/>

      </xsl:template>



      <xsl:template match="bookList">

        {"columns":

          [{"label":"Title","id":"Title"},

           {"label":"Author","id":"Author"},

           {"label":"ISBN","id":"ISBN"},

           {"label":"Description","id":"Description"}],

         "rows": [

        <xsl:apply-templates select="book" />

           ]

         }

      </xsl:template>



      <xsl:template match="book">

        {

          "Title" : "<xsl:value-of select="title" />",

          "Author" : "<xsl:value-of select="author" />",

          "ISBN" : "<xsl:value-of select="isbn" />",

          "Description" : "<xsl:value-of
    select="description" />"

        }

        <xsl:if test="(position()!=last())">,</xsl:if>

      </xsl:template>

    </xsl:stylesheet>
  4. Drag-and-drop two jMaki-wrapped Yahoo DataTable widget in the main
    section of the default generated index.jsp.
  5. Change the generated code fragment to use the values from the different
    Jersey endpoints instead of using the static values. The updated code
    fragment will look like:



    <a:widget name="yahoo.dataTable"

      service="/xhp?id=jersey-json" />

    <a:widget name="yahoo.dataTable"

      service="/xhp?id=jersey-xml" />
  6. Deploy the project and now the jMaki-wrapped widgets are now displayed
    in the browser window as shown below. The
    Firebug
    dump shows the data received by jMaki.



 

Please leave suggestions on other TOTD that you'd like to see. A complete
archive is available here.

Technorati:
totd
jersey
jmaki
json
netbeans
glassfish

Related Topics >>