Tuesday October 02, 2007
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:
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).This TOTD explains 2nd and 3rd bullet. The first bullet can be applied following the solution proposed in 2nd bullet.
examples/HelloWorld" project in
NetBeans 6 IDE.jdbc:derby://localhost:1527/sample [app on APP]"
and select Connect. Enter the password as "app" and select "OK".Execute Command..."
and issue the command:create table BOOKS (title varchar(255),
author varchar(255),
isbn varchar(255),
description varchar(255),
PRIMARY KEY (isbn))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 ?');New",
"Entity Classes from Database...".Available Tables", select "BOOKS"
and click on "Add >". Click on "Next >".Create Persistence Unit...", take all the
defaults and click on "Create" and then click on "Finish".@NamedQuery(name = "Books.findAll",
query = "SELECT b FROM Books b")" to the generated Books class.@javax.xml.bind.annotation.XmlRootElement"
to the generated Books class.com.sun.ws.rest.samples.helloworld"
package, select "New", "Java Class..." and
enter the Class Name as "BookList".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;
}
}com.sun.ws.rest.samples.helloworld.resources",
select "New", "Java Class..." and enter the
Class Name as "TableResource".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;
}
}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).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);Properties", choose "Libraries"
and add the following JARs by clicking on "Add JAR/Folder"
button:GLASSFISH_HOME/javadb/lib/derbyclient.jar"GLASSFISH_HOME/lib/toplink-essentials.jar"GLASSFISH_HOME/lib/toplink-essentials-agent.jar"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:
jMaki Ajax Framework"
for the project.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"
}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><a:widget name="yahoo.dataTable"
service="/xhp?id=jersey-json" />
<a:widget name="yahoo.dataTable"
service="/xhp?id=jersey-xml" />

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
Posted by Arun Gupta in web2.0 | Comments[5]
|
|
|
|
Today's Page Hits: 18671
Hi,
As is usual very good tutorial. Well-explained and clean.
Thank's for your help.
Posted by Freetrax on October 03, 2007 at 12:31 AM PDT #
I'll need a search with grabs the data from by Database maybe with the autocompleter.
Have you a sample for this problem??
Posted by Anja on October 30, 2007 at 12:05 PM PDT #
I am getting:
javax.persistence.PersistenceException: No Persistence provider for EntityManager named HelloWorldPU
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:89)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
at resources.TableResource.getBooks(TableResource.java:63)
I checked that persistence.xml exists, in the correct places, and db connection is fine.
I think this has to do with a deployment issue, but I could not figure out on my own.
One thing that is not clear is on the article in #3
Expand "Web pages", "resources", "xsl" and add a new stylesheet.
what is the name of the stylesheet? Is not mentioned in the article.
Best Regards,
-C.B.
Posted by cambazz@gmail.com on November 28, 2007 at 08:14 PM PST #
I updated the blog with the stylesheet name. Did you check the PU name in persistence.xml is the same as used in the JPA code ?
Posted by Arun Gupta on December 13, 2007 at 11:45 PM PST #
Posted by Arun Gupta's Blog on January 24, 2008 at 04:46 AM PST #