Skip to main content

example using jMaki and RESTful Web Services

Posted by caroljmcdonald on July 18, 2008 at 4:02 PM PDT




http-equiv="content-type">
Sample Application using jMaki and the Java Persistence APIs

a Dynamic Ajax table example using jMaki
and RESTful Web Services on Glassfish



This Sample Catalog app demonstrates a RESTful Web Service, coded using
JAX-RS: Java API
for RESTful Web Services (JSR-311)
and href="http://java.sun.com/javaee/technologies/persistence.jsp">Java
Persistence API,
which provides a list
of customers, and a jMaki
client which  gets and displays the Web Service responses in
a dynamic Ajax table.



href="https://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=9370&expandFolder=9370&folderID=7555">Download
the jMaki Sample Application Code



jMaki is an Ajax framework
that
provides a lightweight model for creating JavaScript centric
Ajax-enabled web applications. jMaki provides wrapped href="http://developers.sun.com/docs/web/swdp/r1/tutorial/doc/p13.html">
widgets that can be used as JavaServer Pages tags, as JavaServer
Faces components, within a Phobos application, or with PHP. This sample
applicaton uses jMaki with JavaServer Pages.



JAX-RS provides a
standardized API for building RESTful web services in Java. Central to
the RESTful architecture is the concept of resources identified by
universal resource identifiers (URIs). The API  provides a set of
annotations which you can add to Plain Old Java Objects (POJOs) 
to expose web resources identified by URIs .


Explanation of the usage of jMaki and JAX-RS in a sample Catalog
Application

The image below shows the Customer Listing page, which allows the user
to
page through a list of customers.


pagingtable.jpg src="http://weblogs.java.net/blog/caroljmcdonald/pagingtable.jpg"
height="369" width="453">


jMaki dataTable widget

With  jMaki and JavaServer Pages, you can easily include wrapped
widgets
from ajax toolkits into a JavaServer Page as a custom JSP tag. href="http://www.netbeans.org/kb/55/framework-adding-support.html">With
the Netbeans jMaki plugin you can drag  jMaki widgets from the
Palette into a JSP. jMaki standardizes widget data and event models
to simplify the
programming model and to simplify interactions between widgets.



The sample application's index.jsp page uses a jMaki yahoo.dataTable
widget to display a  list of
customers in a dynamic table.



The jMaki table widgets (there is also a jMaki dojo table
widget) are useful when you want to show a set of
results in tabular data on a web page.  Table widgets provide
sortable columns, row selection, and they can
be updated using jMaki publish subscribe events.



In the List.jsp
web page the dataTable is defined as shown below:   (Note: style="color: rgb(204, 0, 0); font-weight: bold;">Red colors
are for jMaki
tags or variables, 
and Green
for my code
or variables)


Code Sample from: 
 style="color: rgb(0, 0, 0);">index.jsp


      name="yahoo.dataTable"

          style="color: rgb(204, 0, 0); font-weight: bold;">subscribe= style="color: rgb(204, 0, 0);">" style="font-weight: bold; color: rgb(204, 0, 0);">/table style="color: rgb(204, 0, 0);">"

          style="color: rgb(204, 0, 0); font-weight: bold;">service=" style="color: rgb(0, 102, 0);">webresources/customers/jMakiTable" style="font-weight: bold;">/>

     

     



To determine the data format and events for the
table you can refer to the  href="http://wiki.java.net/bin/view/Projects/jMakiTableDataModel">jMaki
Table Data Model or look at
the widget.json file for the table widget. This file is located in the
resources/yahoo/dataTable directory.



The service
attribute references the 

 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);">customers/jMakiTable
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);"> 
RESTful web
service
which returns the data to be
included
in the table.  The data for the table should be a
JSON object containing an object of
columns and an array of row arrays. The column names need a unique id
which is then used in the data to associate it with a given row. An
example for a table of companies is shown below:




Code Sample from: 
 style="color: rgb(0, 0, 0);">widget.json
 style="color: rgb(204, 0, 0); font-weight: bold;">{

 'columns':[

     {'label' :'Company', 'id' : 'name'},

     {'label':'City', 'id' : 'city'},

     
     {'label':'City', 'id' :
'state'}


 ],

 'rows':[

     {'name' : 'Sun Microsystems', 'city' : 'Santa
Clara',
'state' : 'CA'
},

     
     {'name' : 'IBM', 'city' :
'Raleigh',
'state' :
'NC'
}


 ]

}

     

     





The

 style="color: rgb(204, 0, 0); font-weight: bold;">subscribe= style="color: rgb(204, 0, 0);">" style="font-weight: bold; color: rgb(204, 0, 0);">/table style="color: rgb(204, 0, 0);">"

attribute specifies a topic that events can be
sent to. Publish and subscribe events can be used to tie widgets
together (more on this later).


RESTful  Web Services with JAX-RS



The dataTable's

 style="color: rgb(204, 0, 0); font-weight: bold;">service

attribute references the style="font-weight: bold;"> URI 
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);">webresources/customers/jMakiTable
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);"> 
for the
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);">customers jMakiTable
 
RESTful web service.  The customers
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);">
RESTful web
service was generated using Netbeans 6.1 as explained in the href="http://www.netbeans.org/kb/61/websvc/rest.html">Generating
RESTful Web Services from Entity Classes  tutorial. 
Using Netbeans 6.1 you can generate JPA Entity Classes from Database
tables, then you can Generate RESTful Web Services from Entity
Classes, and then you can test the Web Services with a browser
interface. The customers
 style="color: rgb(204, 0, 0); font-weight: bold;"> style="color: rgb(0, 102, 0);">
RESTful web
service was generated from the customer data table which comes already
created in the Java DB with Netbeans.  I added the jMakiTable
method to the generated customers Web Service,  in order to return
the customers in the jMaki table format. I followed the jMakiBackend
example which comes with Jersey
(the JAX-RS reference implementation)

which is expained in Japods blog:  href="http://blogs.sun.com/japod/entry/jmaki_widgets_talking_to_jersey">jMaki
Widgets Talking To Jersey Resources In JSON.





Below is a snippet from the
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource
.java
class which was generated by the Netbeans "Generate RESTful Web
Services
from Entity Classes" feature :


Code Sample from:
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource
.java


      // Service URI path
"/customers/"
style="color: rgb(0, 0, 153); font-weight: bold;">

@Path("/customers/")

public class CustomersResource
{

  

         style="font-weight: bold;">  @GET style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-weight: bold;">
          style="color: rgb(0, 0, 153); font-weight: bold;">@ProduceMime("application/json")

    public
CustomersConverter
      get( style="color: rgb(0, 0, 153); font-weight: bold;">@QueryParam("start")

            style="color: rgb(0, 0, 153); font-weight: bold;">@DefaultValue("0")
int start, @QueryParam("max")

           
@DefaultValue("4") int max, @QueryParam("expandLevel")

           
@DefaultValue("1") int expandLevel, @QueryParam("query")

           
@DefaultValue("SELECT e FROM Customer e") String query) {

        try {

           
CustomersConverter custs = new CustomersConverter(

               
      getEntities(start,
max, query),

               
context.getAbsolutePath(), expandLevel);

           
return
custs
;

        } finally {

           
PersistenceService.getInstance().close();

        }

    }

      style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-family: monospace;">


     



The CustomersResource
represents a list of customers. The

 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource
 
get method
returns a list of Customer objects in JSON
format. 

  • To address a resource in REST you specify its URI. 
     style="color: rgb(0, 0, 153); font-weight: bold;">@Path 
    is
    a JAX-RS annotation that identifies the URI path for the resource. For
    the CustomersResource 
    the URI path is /
     style="color: rgb(0, 0, 153); font-weight: bold;"> style="color: rgb(0, 102, 0);">customers
    /.
     style="color: rgb(0, 0, 153);"> 

       
  •  style="font-weight: bold;">@GET 
    specifies
    that the
    get
       
    method supports the HTTP GET method.
     style="color: rgb(0, 0, 153); font-weight: bold;">
  • @ProduceMime
       
    specifies the MIME types that a method can produce.
    Here,
    the annotation specifies that the
     style="color: rgb(0, 102, 0); font-weight: bold;">get

    method returns a JSONArray object.  The
     style="color: rgb(0, 102, 0); font-weight: bold;">CustomersConverter
       
    class is a JAXB
    annotated class which is used to marshal a list of Customer objects
    into XML or href="http://wikis.sun.com/display/Jersey/JSON+support+in+JAXB">JSON
    format.   The
     style="font-weight: bold; color: rgb(0, 102, 0);">getEntities 
     style="color: rgb(0, 102, 0); font-weight: bold;">
    method
    returns a list of Customer entity objects and is explained
    below.  
     style="color: rgb(0, 0, 153); font-weight: bold;">
  • @QueryParam
       
    specifies
    input parameters for methods.  When the method is invoked, the
    input value will be injected into the corresponding input
    argument. 
     style="color: rgb(0, 0, 153); font-weight: bold;">
  • @DefaultValue
       
    specifies a default value for an arguement if no
    input
    value is given.

Here is an example of an HTTP request for this Web Service:


Request: GET
http://host/jMakiRest/webresources/customers/?start=0




Here is an example of an HTTP response for this Web Service:


Received:

{"customers":

  {"@uri":"http://host/jMakiRest/webresources/customers/",

   "customer":[

    
{"@uri":"http://host/jMakiRest/webresources/customers/1/",

       "name":"JumboCom",

      "city":"Fort
Lauderdale",     

       "state":"FL",

       "zip":"33015"},

    
{"@uri":"http://host/jMakiRest/webresources/customers/2/",

       "name":"Livermore Enterprises",

       "city":"Miami",

       "state":"FL",

       "zip":"33055"}

    ]

  }

}





Below is the

 style="color: rgb(0, 102, 0); font-weight: bold;">getTable 
method 
from the CustomersResource.java
 style="color: rgb(0, 102, 0); font-weight: bold;">
 style="color: rgb(0, 102, 0); font-weight: bold;">

class,  which returns a list of Customers in the jMaki  JSON
table format.


Code Sample from:
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource
.java
 style="font-weight: bold; color: rgb(204, 0, 0);"> style="color: rgb(0, 0, 153); font-weight: bold;">

public class CustomersResource
{

     . . .

  

         style="font-weight: bold;">  @GET style="color: rgb(0, 0, 153); font-weight: bold;">
         
@Path("/jMakiTable")


          style="color: rgb(0, 0, 153); font-weight: bold;">@ProduceMime("application/json")

    public CustomerTableModel style="color: rgb(0, 102, 0); font-weight: bold;">getTable( style="color: rgb(0, 0, 153); font-weight: bold;">@QueryParam("start")

            style="color: rgb(0, 0, 153); font-weight: bold;">@DefaultValue("0")
int start, @QueryParam("max")

           
@DefaultValue("4") int max, @QueryParam("expandLevel")

           
@DefaultValue("1") int expandLevel, @QueryParam("query")

           
@DefaultValue("SELECT e FROM Customer e") String query) {

     

        CustomersConverter custs = style="color: rgb(0, 102, 0); font-weight: bold;">get(start,
max,

                  
expandLevel, query);

        return new style="color: rgb(0, 102, 0); font-weight: bold;">CustomerTableModel(custs.getCustomer());

    }

      style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-family: monospace;">


     



The

getTable
method calls the
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource

get
method, explained above,  to get a list of Customer Entities which
are used to create a
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomerTableModel

class. The
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomerTableModel

class is a JAXB annotated
class, used to marshal a list of Customer objects into the jMaki 
JSON table format.  A snippet of the
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomerTableModel

class is shown below:




border="1" cellpadding="2" cellspacing="0">
Code Sample from:
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomerTableModel
.java
 style="font-weight: bold; color: rgb(204, 0, 0);"> style="color: rgb(0, 0, 153); font-weight: bold;">

      @XmlRootElement

public class CustomerTableModel {

     

    public static class JMakiTableHeader {

     

        public String style="font-weight: bold;">id;

        public String style="font-weight: bold;">label;

     

        public
JMakiTableHeader(String id,

           String
label) {

           
this.id = id;

           
this.label = label;

        }

    }

    public List style="font-weight: bold;">columns =

          initHeaders();

    public List style="font-weight: bold;">rows;

  

         style="font-weight: bold;">  . ..

      style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-family: monospace;">


     




Java Persistence Query API

The CustomersResource

 style="color: rgb(0, 102, 0); font-weight: bold;"> 
getEntities
method

uses the Java Persistence API style="color: rgb(204, 0, 0);">
Query
 style="color: rgb(204, 0, 0); font-weight: bold;"> 
object
to return a list of customers.


Code Sample from:
 style="color: rgb(0, 102, 0); font-weight: bold;">CustomersResource
.java
 style="font-weight: bold; color: rgb(204, 0, 0);"> style="color: rgb(0, 0, 153); font-weight: bold;">

@Path("/customers/")

public class CustomersResource
{

  

          .
. .

      style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-family: monospace;">

    protected Collection style="font-weight: bold;">getEntities(int
start, int max, String query) {

       
PersistenceService
ps =
PersistenceService.getInstance();

        Query query = ps.
createQuery(query);

        query.
setFirstResult(start);

     
        query.setMaxResults(max);

        return query.
getResultList();

    }

     


 

     



The Java
Persistence href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html">Query
APIs are used to create and execute queries that can return a
list of results.  The JPA Query interface provides
support for pagination via the setFirstResult() and setMaxResults()
methods: query. style="color: rgb(0, 0, 0);">setMaxResults(int maxResult)
sets the maximum number of results to retrieve. style="font-family: mon;"> query. style="color: rgb(0, 0, 0);">setFirstResult(int startPosition)
sets the position of the first result to retrieve.




In the code below, we show the

 style="color: rgb(0, 102, 0); font-weight: bold;">Customer

entity class which maps to the  CUSTOMER table that stores the
customer instances. This is a
typical Java Persistence entity object. There are two requirements for
an entity:

  1. annotating the class with an
     style="font-weight: bold; color: rgb(0, 0, 153);">@Entity

    annotation.
  2. annotating the primary key identifier with @Id
     


Because the fields name, description.... are basic mappings from the
object fields to columns of the same name in the database table, they
don't have to be annotated. 

For more information on Netbeans and JPA see href="http://www.apress.com/book/bookDisplay.html?bID=10093"> href="http://www.netbeans.org/kb/55/persistence.html">basics of
developing a web application using Java™ Persistence API.





 
   
     
Code Sample from: style="color: rgb(0, 102, 0); font-weight: bold;">Customer.java


      @Entity style="color: rgb(0, 0, 0);">
      style="color: rgb(0, 0, 0);">

      public class style="font-weight: bold; color: rgb(0, 102, 0);"> style="font-family: monospace;">Customer style="color: rgb(0, 0, 0);">
implements Serializable {

     

         
@Id
  

    private Integer customerId;


    private String name;

    private String addressline1;   

    private String city;  

    private String state; 

    private String zip;


          

    public
 style="font-weight: bold;">Customer
() { }

     

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }
 style="color: rgb(0, 0, 0);">
     

     
 style="color: rgb(0, 0, 0);"> 

      }   

     

     
 style="font-weight: bold;">

jMaki Publish Subscribe events 

jMaki publish subscribe events tie widgets actions together. The sample
app
uses two jMaki

 style="color: rgb(204, 0, 0); font-weight: bold;">yahoo.button 
widgets
which publish to the
/button/previous,
/button/next 
 style="color: rgb(204, 0, 0); font-weight: bold;">topics
style="font-weight: bold;">
when the respective button is clicked:


Code Sample from:
List style="color: rgb(0, 0, 0);">.jsp


      name="yahoo.button" value="{label : '<<',

                
action : {topic
: '/button/previous'}}"
/>

     

      name="yahoo.button" value="{label : '>>',

                
action : {topic
: '/button/next'}}"
/>

     

     



Events in jMaki are handled by href="https://ajax.dev.java.net/introGlue.html">jMaki Glue , which href="https://ajax.dev.java.net/introGlue.html"> allows JavaScript
components to talk to each
other. You put function listeners which Subscribe to topics that your
widgets Publish to in a file called glue.js (to read more about this
see A practical
guide to jMaki Events
).



Connecting the listener to the handler

 


The listener handler for the 

 style="color: rgb(0, 102, 0); font-weight: bold;">/button/next 
 style="color: rgb(204, 0, 0); font-weight: bold;">topic 
 style="color: rgb(0, 102, 0); font-weight: bold;">
is
shown below. First you declare the topic to listen to and then the
listener function which will handle the notification. The
 style="color: rgb(0, 102, 0); font-weight: bold;">/button/next 
listener
handler  increments the page number and then calls the
 style="color: rgb(0, 102, 0); font-weight: bold;">getNextPage

funtion.


border="1" cellpadding="2" cellspacing="0">
Code Sample from:
 style="font-weight: bold;">glue.js
var page= 0;

var start= 0;

var batchSize=4;

     

      jmaki.subscribe(" style="color: rgb(0, 102, 0); font-weight: bold;">/button/next",
function(args) {

    page =page + 1;

    style="color: rgb(0, 102, 0); font-weight: bold;">getNextPage(page);

});

     

      jmaki.subscribe(" style="color: rgb(0, 102, 0); font-weight: bold;">/button/previous",
function(args) {

    page =page - 1;

    if (page < 0) page = 0;

    style="color: rgb(0, 102, 0); font-weight: bold;">getNextPage(page);

});

     

function getNextPage(page)
{

    start = page * batchSize;

    style="color: rgb(204, 0, 0); font-weight: bold;">jmaki.doAjax({method:
"POST",

        style="color: rgb(204, 0, 0); font-weight: bold;">url: " style="color: rgb(0, 102, 0); font-weight: bold;">webresources/customers/?start="+encodeURIComponent(start),

        style="color: rgb(204, 0, 0); font-weight: bold;">callback :
function(req)
{

            style="color: rgb(0, 102, 0); font-weight: bold;"> style="font-family: monospace;">var
respObj = eval('('+ req.responseText +')');
style="color: rgb(0, 0, 0);">
                 
var rows =  respObj.customers.customer;


                 
      jmaki.publish(" style="color: rgb(0, 102, 0); font-weight: bold;">/table/ style="color: rgb(204, 0, 0); font-weight: bold;">clear", { });

           
for(j=0;j
               
var row = rows[j];

               
      jmaki.publish("/ style="color: rgb(0, 102, 0);">table/ style="color: rgb(204, 0, 0); font-weight: bold;">addRow",{

                   
      value:
      row

               
});

            }

            style="color: rgb(204, 0, 0); font-weight: bold;">

        }

    });    

}

     
       



The getNextPage
function uses 

 style="color: rgb(204, 0, 0); font-weight: bold;">jmaki.doAjax
,
which
provides an easy way to make an  XMLHttpRequest, to call the
 style="color: rgb(0, 102, 0); font-weight: bold;">/customers/

RESTful
Web Service  passing the start index  as a URI
parameter.  The 
 style="color: rgb(204, 0, 0); font-weight: bold;">callback 
function
uses  eval to convert the XMLHttpRequest response
into a JSON object. Then 
 style="color: rgb(204, 0, 0); font-weight: bold;">jmaki.publish

is called to publish the returned
 style="color: rgb(0, 102, 0); font-weight: bold;">customer

JSON objects to the
 style="font-weight: bold; color: rgb(0, 102, 0);">/table/ style="color: rgb(204, 0, 0); font-weight: bold;">addRow 
topic.



The
yahoo.dataTable
widget
subscribes to the
 style="color: rgb(204, 0, 0);">
 style="color: rgb(204, 0, 0); font-weight: bold;">  style="color: rgb(0, 102, 0); font-weight: bold;">table 
topic.

Subscribe events allow you to manipulate a given instance of a widget.
The event names are appended to the the subscribe topic name following
a "/". For example  "
 style="font-weight: bold; color: rgb(0, 102, 0);">/table/ style="color: rgb(204, 0, 0); font-weight: bold;">addRow
"
will call the
 style="color: rgb(204, 0, 0); font-weight: bold;">yahoo.dataTable 
href="http://wiki.java.net/bin/view/Projects/jMakiTableDataModel">addRow
function which will add the  payload value passed to the widget to
the the table. This will cause the  returned
 style="color: rgb(0, 102, 0); font-weight: bold;">customer

JSON object to be displayed in the table on the html page.





Conclusion

This concludes the sample application which  demonstrates a
RESTful Web Service, coded using
JAX-RS: Java API
for RESTful Web Services (JSR-311)
,
which provides a list
of customers, and a  jMaki 
client which  gets and displays the Web Service responses in
a dynamic Ajax table.

Configuration of the Application
for jMaki, JPA, Netbeans 6.1 and Glassfish V2

  • Download
    and install NetBeans 6.1 bundled with GlassFish V2
  • Alternatively you can  href="https://glassfish.dev.java.net/public/downloadsindex.html">Download
    and install GlassFish V2 separately.
  • Download
    and install the href="http://www.netbeans.org/kb/55/framework-adding-support.html">jMaki
    plug-in in the NetBeans update center.


Open and Run the Sample code:

  1. Download the href="https://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=9370&expandFolder=9370&folderID=7555">sample
    code and extract its contents. You should now see the newly
    extracted directory as /jmakiRest,
    where is the directory where
    you installed the sample package. For example, if you extracted the
    contents to C:\ on a Windows machine, then your newly
    created directory should be at C:\jmakiRest.


  2. Start the NetBeans IDE. Click Open Project in the File menu and
    select the jmakiRest directory you just
    unzipped.


  3. Build the project as follows:


    • Right click the jmakiRest
       node in
      the
      Projects window.

           

    •      
    • Select Clean and Build Project.

             

           

    •    

     

  4.  
  5. Run the project as follows:

       

       

           
    • Right click the jmakiRest node in
      the
      Projects window.
    • Select Run Project.

When you run the project, your browser should display the opening page
of the Sample Application (at
http://localhost:8080/jmakiRest/).





If you want to create your own jMaki
application:

  • check out Arun Gupta's href="http://blogs.sun.com/arungupta/entry/dynamic_data_in_jmaki_widgets">blog
    and screencasts. href="http://blogs.sun.com/arungupta/entry/dynamic_data_in_jmaki_widgets">

References:








Related Topics >>