 |
Dynamic Ajax table example using jMaki and Java Persistence APIs on Glassfish
Posted by caroljmcdonald on February 08, 2008 at 10:52 AM | Comments (6)
Sample Application using jMaki and the Java Persistence APIs
a Dynamic Ajax table example using jMaki
and Java Persistence APIs on Glassfish
This Sample Catalog app demonstrates the usage of the Java
Persistence APIs to implement server side pagination (recommended for
large sets of data), and jMaki to get and display the results in
a dynamic Ajax table.
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
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.
Explanation of the usage of jMaki and the Java Persistence
APIs in a sample Catalog Application
The image below shows the Customer Listing page, which allows the user
to
page through a list of customers.
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. 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: Red colors
are for jMaki
tags or variables,
and Green
for my code
or variables)
Code Sample from: index.jsp |
<a:widget
name="yahoo.dataTable"
subscribe="/table"
service="CatalogService"/>
|
To determine the data format and events for the
table you can refer to the 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 CatalogService servlet
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: widget.json |
{
'columns':[
{'label' :'Company', 'id' : 'name'},
{'label':'City', 'id' : 'city'}
],
'rows':[
{'name' : 'Sun Microsystems', 'city' : 'Santa
Clara'},
{'name' : 'IBM', 'city' :
'Raleigh'}
]
}
|
The publish
subscribe
attributes specify a topic that publish and subscribe events will be
sent to. Publish and subscribe events can be used to tie widgets
together (more on this later).
The dataTable's service="CatalogService" calls the CatalogService servlet
which calls the getCustomersJSON method
of the Catalog
class:
Code Sample from: Catalog.java |
public class Catalog
{
public List<Customer> getCustomers()
throws Exception {
EntityManager
em
= getEntityManager();
Query
q = em.createQuery(
"select object(o) from Customer as o");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
return q.getResultList();
}
public JSONArray getCustomersJSON()
throws Exception {
JSONArray customersJSON = new JSONArray();
List<Customer> customers = getCustomers();
for (Customer customerData : customers) {
JSONObject
customerJSON = customerData.toJSON();
customersJSON.put(customerJSON);
}
return customersJSON;
}
|
Java Persistence Query API
The Catalog getCustomersJSON()
uses the Java Persistence API Query object
to return a list of customers, a JSONArray
object is used to return the list in JSON format. The Java
Persistence 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.setMaxResults(int maxResult)
sets the maximum number of results to retrieve. query.setFirstResult(int startPosition)
sets the position of the first result to retrieve.
In the code below, we show the 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:
- annotating the class with an
@Entity
annotation.
- 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 basics of
developing a web application using Java™ Persistence API.
Code Sample from: Customer.java |
@Entity
public class Customer
implements Serializable {
@Id
private Integer customerId;
private String name;
private String addressline1;
private String city;
private String state;
private String zip;
public Customer() { }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
...
public JSONObject toJSON()
{
JSONObject thisJSON=new
JSONObject();
thisJSON.put("name",
this.getName());
thisJSON.put("city",
this.getCity());
thisJSON.put("state",
this.getState());
thisJSON.put("zip",
this.getZip());
}
}
|
I added the toJSON() method to
the Customer to return a JSON
representation of the Customer entity.
jMaki Publish Subscribe events
jMaki publish subscribe events tie widgets actions together. The sample
app
uses two jMaki yahoo.button widgets
which publish to the
/button/previous,
/button/next topics
when the respective button is clicked:
Code Sample from: List.jsp |
<a:widget
name="yahoo.button" value="{label : '<<',
action : {topic
: '/button/previous'}}"
/>
<a:widget
name="yahoo.button" value="{label : '>>',
action : {topic
: '/button/next'}}"
/>
|
Events in jMaki are handled by jMaki Glue , which 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 /button/next topic is
shown below. First you declare the topic to listen to and then the
listener function which will handle the notification. The /button/next listener
handler increments the page number and then calls the getNextPage
funtion.
Code Sample from: glue.js |
var page= 0;
jmaki.subscribe("/button/next",
function(args) {
page =page + 1;
getNextPage(page);
});
jmaki.subscribe("/button/previous",
function(args) {
page =page - 1;
if (page < 0) page = 0;
getNextPage(page);
});
function getNextPage(page)
{
jmaki.doAjax({method:
"POST",
url: "CatalogService?page="+encodeURIComponent(page)+
"&rowsonly=" +
encodeURIComponent(rowsonly),
callback :
function(req)
{
customers
= eval(req.responseText);
jmaki.publish("/table/clear", { });
jmaki.publish("/table/addRows",
{ value
: customers}
);
}
});
}
|
The getNextPage
function uses jmaki.doAjax,
which
provides an easy way to make an XMLHttpRequest, to call the CatalogService
servlet passing the page number as a URI parameter. The callback function
uses eval to convert the XMLHttpRequest response
into a JSON object. Then jmaki.publish
is called to publish the returned customers
JSON object to the /table/addRows topic.
The yahoo.dataTable
widget subscribes to the 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 "/table/addRows"
will call the yahoo.dataTable addRows
function which will add the payload value passed to the widget to
the the table. This will cause the returned customers
JSON object to be displayed in the table on the html page.
This CatalogServlet
processRequest
method is defined as shown below:
Code Sample from: CatalogBean.java |
public class CatalogServlet
extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
Catalog
catalog = new Catalog();
response.setContentType("text/plain;charset=UTF-8");
PrintWriter out = response.getWriter();
int page =
Integer.parseInt(request.getParameter("page"));
int rowsonly =
Integer.parseInt(request.getParameter("rowsonly"));
JSONArray array =
catalog.getNextCustomersJSON(page);
if (rowsonly == 1) {
out.println(array.toString());
} else{
out.println("{columns
: [" +
"{ label : 'Company', id :
'name'}," +
"{ label :'City', id :
'city'}," +
"{ label : 'State', id :
'state'}," +
"{ label : 'Zip', id :
'zip'}" +
"],");
out.println("rows:
");
out.println(array.toString());
out.println(" }");
}
out.close();
}
|
The CatalogServlet
simply calls the Catalog
class to get the next list of results from the database like we saw in
the
previous code. The CatalogServlet then
returns the resulting JSONArray
as a text string.
Conclusion
This concludes the sample application which demonstrates the usage of
the Java
Persistence APIs and jMaki in a dynamic Ajax table example.
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 Download
and install GlassFish V2 separately.
- Download
and install the jMaki
plug-in in the NetBeans update center.
Open and Run the Sample code:
- Download the sample
code and extract its contents. You should now see the newly
extracted directory as
<sample_install_dir>/JPAjmaki,
where <sample_install_dir> 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:\JPAjmaki.
- Start the NetBeans IDE. Click Open Project in the File menu and
select the
JPAjmaki directory you just
unzipped.
- Build the project as follows:
- Right click the
JPAjmaki node in
the
Projects window.
- Select Clean and Build Project.
- Run the project as follows:
- Right click the
JPAjmaki 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/JPAjmaki/).
If you want to create your own jMaki
application:
- check out Arun Gupta's blog
and screencasts.
References:
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
-RestApi missing in Project.
-Praful
Posted by: dynamicmethods on March 25, 2008 at 10:06 AM
-
Hi Carol :
I use your sample code to do a dynamic ajax table. But i encountered some problems. The following code : rows : ${catalogBean.customersJSON}} dosen't work. It just return a ["xxxx", "xxxx", "xxxx"] type of string, not the required format string like {'name' : 'Sun Microsystems', 'city' : 'Santa Clara'}.
I reference to the article of Dynamic Data in jMaki Widgets Using JPA. It create a data.jsp page to provide the required format string for jMaki.
What can i do to follow your method to do the same thing?
Thanks.
Posted by: yummychen on May 01, 2008 at 11:45 PM
-
you're right, its not working anymore, I will try to update it
Posted by: caroljmcdonald on June 05, 2008 at 03:54 PM
-
I updated the code.
Posted by: caroljmcdonald on June 12, 2008 at 01:49 PM
-
I'm a bit confused on this. I am working with jMaki 1.8.1.1 in NetBeans. When I reproduce your code exactly, the code seems to return an object reference and the table does not update:
function returnUser(userid) {
jmaki.doAjax({method: "GET",
url: "UserLookup?userid=" + encodeURIComponent(userid),
callback : function(req) {
users = eval(req.responseText);
jmaki.publish("/table/ldapusertable/clear", { });
jmaki.publish("/table/ldapusertable/addRows",{value: users});
}
});
}
Publish : Topic: /table/ldapusertable/clear message {}
Publish : Topic: /table/ldapusertable/addRows message {value : [[object Object]]}
When I remove the {value: users} wrapper and the publish looks like this, the result is the JSONArray, but the table still does not update:
jmaki.publish("/table/ldapusertable/addRows",users);
Publish : Topic: /table/ldapusertable/addRows message [{lastname : 'Monday' , firstname : 'Paul' , userid : '1111' , email : 'Paul.Monday@Sun.COM'}]
Is there some subtle conversion I'm missing on this one?
Paul
Posted by: pmonday on March 30, 2009 at 07:40 PM
-
this example was published February 08, 2008. jMaki probably changed something since then. Better to ask at
http://forums.java.net/jive/forum.jspa?forumID=96
Posted by: caroljmcdonald on March 30, 2009 at 08:12 PM
|