REST, dojo, Comet
Carol McDonald, Java Architect
2
About the Speaker
• Carol cDonald: > Java Architect at Sun Microsystems> Before Sun, worked on software development of:
●Application to manage car Loans for Toyota (>10 million loans)
●Pharmaceutical Intranet apps (Roche Switzerland) ●Telecom Network Mgmt (Digital France) ●X.400 Email Server (IBM Germany)
3
Agenda
• REST and JAX-RS• Dojo • Comet
4
Example RESTful Catalog
5
RESTful Slideshow using JAX-RS and comet
6
REST and JAX-RSREST and JAX-RS
7
REpresentational State Transfer
Client State1 Client State2
REST Web ServiceGet http://www.parts-depot.com/parts
Response XML data =REpresentational State
Transfer
● The URL identifies the resource● GET the page from the server● html page is transferred to the browser
– REpresentational State transfer● You click on a hyperlink in page (hypermedia), the process is repeated● The page (application state) is stored on the client (browser)
8
REST Tenets
• Resources (nouns)> Identified by a URI, For example:
●http://petstore/catalog/items/
• Methods (verbs) to manipulate the nouns> Small fixed set:
●GET=Read, PUT=Update, POST=Create, Delete
• Representation of the Resource > data and state transferred between client and server> XML, JSON...
• Use verbs to exchange application state and representation
9
HTTP ExampleRequestGET /catalog/items HTTP/1.1Host: petstore.comAccept: application/xml
ResponseHTTP/1.1 200 OKDate: Tue, 08 May 2007 16:41:58 GMTServer: Apache/1.3.6Content-Type: application/xml; charset=UTF-8
<?xml version="1.0"?><items xmlns="…"> <item>…</item> …</items>
Method Resource
Representation
Statetransfer
10
JAX-RS: Clear mapping to REST concepts
• High level, Declarative> Uses @ annotation in POJOs
• Resources: what are the URIs?@Path("/items/{id}")
• Methods: what are the HTTP methods?@GETpublic XXX find()
• Representations: what are the formats?@Consumes("application/xml")@Produces("application/json")
11
Example RESTful Catalog
12
Example RESTful Catalog Service
CatalogDatabase
TestClient
dojoClient
Web container(GlassFish™)
+REST API
Browser(Firefox)
Resource Classes
Convertor Classes
Entity Classes
HTTP
13
URIs and Methods:
● /items– GET - list all items– POST – add item to catalog
/items/{id}> GET - get an item representation> PUT - update an item> DELETE – remove an item
Item Catalog Example
http://www.infoq.com/articles/rest-introduction
14
POJO
@Path("/items/")public class ItemsResource {
@Produces("application/json") @GET public ItemsConverter get() { ... }
...}
responds to the URI http://host/catalog/items/
responds with JSON
responds to HTTP GET method
resource
Representation
15
Methods @Path(“/items”)class ItemsResource { @GET Items get() { ... } @POST Response create(Item) { ... }}
class ItemResource { @GET Item get(...) { ... } @PUT void update(...) { ... } @DELETE void delete(...) { ... }} Java method name is not significant
The @HTTP method is the method
16
RESTful Catalog
DB
Registration Application
JAX-RS class
Dojo clientJAXB class
Entity Class
ItemsConverter
Item
ItemsResource
● Dojo client, JAX-RS, JAXB, JPA
17
Entity Classes• Use JPA to map/retrieve data from the database as
entities• expose entities as RESTful resources
> entity = resource identified by URL
public class Item {
int id; String name; String descr; String url;
}
@Entity
@Id
ItemID NAME DESC URL
http://host/catalog/items/123
18
Converter Classes
• JAXB to convert the domain objects (JPA entities) into XML and/or JSON.
DB
JAX-RS class
Dojo clientJAXB class
Entity Class
ItemsConverter
Item
ItemsResource
19
ItemConverter JAXB annotated @XmlRootElement(name = "item")public class ItemConverter { private Item entity; private URI uri;
@XmlAttribute public URI getUri() { return uri; } @XmlElement public Long getId() { return (expandLevel > 0) ? entity.getId() : null; } ... }
20
XML
<item uri="http://localhost/Web/resources/items/1/"> <description> black cat is nice</description> <id>1</id> <imagethumburl>/images/anth.jpg</imagethumburl> <name>not Friendly Cat</name> <price>307.10</price> <productid>feline01</productid> </item>
21
JSON
{ "@uri":"http://host/catalog/resources/items/1/", "name":"Friendly Cat", "description":"This black and white colored cat is super friendly.", "id":"1", "imageurl":"http://localhost:8080/CatalogService/images/anthony.jpg" }
22
ItemsConverter JAXB annotated @XmlRootElement(name = "items")public class ItemsConverter { private Collection<ItemConverter> items; private URI uri;
@XmlAttribute public URI getUri() { return uri; } @XmlElement public Collection<ItemConverter> getItem() { ... return items; }}
23
XML<?xml version="1.0" encoding="UTF-8"?> <items uri="http://localhost/Web/resources/items/"> <item uri="http://localhost/Web/resources/items/1/"> <description> black cat is nice</description> <id>1</id> <imagethumburl>/images/anth.jpg</imagethumburl> <name>not Friendly Cat</name> <price>307.10</price> <productid>feline01</productid> </item> <item . . . </item> </items>
24
JSON
{ "@uri":"http://host/catalog/resources/items/", "item":[ {"@uri":"http://host/catalog/resources/items/1/", "name":"Friendly Cat", "description":"This black and white colored cat is super friendly.", "id":"1", "imageurl":"http://localhost:8080/CatalogService/images/anthony.jpg"}, {"@uri":"http://host/catalog/resources/items/2/", "name":"Fluffy Cat", "description":"A great pet for a hair stylist! "id":"2", "imageurl":"http://localhost:8080/CatalogService/images/bailey.jpg"} ] }
25
Resource Classes> Items Resource retrieves updates a collection of Item entities> /items – URI for a list of Items> Item resource retrieves or updates one Item entity> /item/1 – URI for item 1
DB
JAX-RS class
Dojo clientJAXB class
Entity Class
ItemsConverter
Item
ItemsResource
26
Get Items @Path("/items/")public class ItemsResource { @Context protected UriInfo uriInfo; @GET @Produces("application/json") public ItemsConverter get(){ return new ItemsConverter( getEntities(), uriInfo.getAbsolutePath()); }
Performs JPAQuery, returns listof entities
JAXB class
responds with JSON
responds to the URI http://host/catalog/items/
responds to HTTP GET
27
Get Item@Path("/items/")public class ItemsResource {
@Path("{id}/") public ItemResource getItemResource(@PathParam("id") Long id) { return new ItemResource(id, context); }}
public class ItemResource { @GET @Produces("application/json") public ItemConverter get() { return new ItemConverter(getEntity(), context.getAbsolutePath(), expandLevel); }
JAXB class
http://host/catalog/items/123
28
Dojo Client SideDojo Client SideJavaScript LibraryJavaScript Library
29
What is the Dojo Toolkit?
• Open Source set of JavaScript libraries• Simplifies javascript • support
> SitePen, IBM, Sun, JotSpot, Renkoo, AOL TurboAjax, OpenLaszlo, Nexaweb, Bea Systems
• http://dojotoolkit.com/• Server side technology independent,
source: dojotoolkit.org
30
Dojo 3 main parts: Dojo
> Browser normalization, package loading, DOM access and manipulation, Firebug Lite debugging, events, data access, Drag and drop, Asynchronous remote calls, JSON encoding/decoding
dijit > Interface widgets, Advanced UI
controls,Template driven
dojoX> Inventive innovative: graphics, offline, widgets like
grid spreadsheat,
31
LoadingLoading ddojo ojo
32
Use Dojo from Content Distribution Network :
•download nothing and simply pull Dojo from a CDN near you:
AOL: <SCRIPT TYPE="text/javascript" SRC="http://o.aolcdn.com/dojo/1.2.0/dojo/dojo.xd.js"></SCRIPT>
Google: <SCRIPT TYPE="text/javascript" SRC=”http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dojo/dojo.xd.js"></SCRIPT>
script element is responsible for loading the base Dojo script
33
Use Dojo from your Web Server :
• Download from http://dojotoolkit.org/downloads• Unzip the file, rename top folder to src <script type="text/javascript" djConfig="parseOnLoad: true" src="js/dojo/dojo.js" > </script>
script element is responsible for loading the base Dojo script
The package system handles the loading of all other dependencies and modules once dojo.js has been loaded into the page
34
Use bundled Dojo with Netbeans project:
• Create a Netbeans project. Add Netbeans bundled dojo library to project:
35
Or Use downloaded Dojo with Netbeans project:(if you want a different version)
• Download from http://dojotoolkit.org/downloads• Unzip the file, rename top folder to js• Create a Netbeans project. Copy js folder into
the web folder of your Netbeans project :
36
Run File themeTester.html
37
Try out dojo dijit widgets
38
Setting up dojo javascript in the page
<head> <style type="text/css"> @import "js/dojo/resources/dojo.css";"; </style> <script type="text/javascript" src="js/dojo/dojo.js" djConfig="parseOnLoad: true" isDebug: true > </script></head>
Use firebug lite for debugging
Load the dojo style sheet
39
Logging console.log("log button clicked");console.debug("debug button clicked");console.info("info button clicked");console.warn("warn button clicked");console.error("error button clicked");
40
Dijit = Dijit = ddojo Widgetojo Widget
41
dijit is a UI widget system layered on top of dojo
The dojo Widget Library
42
What is a dojo Widget?
• Is a UI element such as a button, text box, scroll bar, calendar, tree etc> Easy to use> Event handlers can be registered on widget> handle browser incompatibilities
• HTML+CSS bound by JavaScript
43
Creating a Button Widget<head> <style type="text/css"> @import "js/dijit/themes/tundra/tundra.css"; @import "js/dojo/resources/dojo.css"; </style> <script type="text/javascript" djConfig="parseOnLoad: true" src="js/dojo/dojo.js" ></script> <script type="text/javascript"> dojo.require("dijit.form.Button"); </script></head><body class="tundra">
<button dojoType="dijit.form.Button" onclick="call_function"> Log Button</button>
Load the Dijit style sheet
Class of widgets matches style Load form button module
For declarative widgets
44
Form Widgets• CheckBox, RadioButton,ComboBox,
CurrencyTextBox, DateTextBox, NumberTextBox, Slider, ValidationTextBox, Textarea
• Attributes: disabled: Boolean• Methods:
> focus Set the focus on this widget > getValue get the value of the widget. > setValue set the value of the widget. > reset resets the widget to it's initial value > undo restore the value to the last value
• Extension Points: onChange: callback function
45
Example dijit.form.DateTextBox
<script>dojo.require("dijit.form.DateTextBox");
</script><body><input type="text" name="date1"
value="2005-12-30"dojoType="dijit.form.DateTextBox"required="true" />
46
Dijit Layout
• Accordion Container,Content Pane, Layout Container, Split Container, Stack Container, Tab Container
47
Dijit Command Control
• Button, ComboButton, DropDownButton, Menu, Toolbar
48
Dojo Event systemDojo Event system
49
dojo.event.connect(srcObj,"srcFunc", targetFunc);
function myFunction() { alert("dojo.connect handler");
}
var link = dojo.byId("mylink");
dojo.event.connect(link, "onclick", myFunction);
<a href="#" id="mylink">Click Me</a>
50
XMLHttpRequest (XHR):XMLHttpRequest (XHR):dojo.xhrDelete(), dojo.xhrDelete(), dojo.xhrGet(), dojo.xhrGet(), dojo.xhrPost(), dojo.xhrPost(), dojo.xhrPut()dojo.xhrPut()
51
Traditional Web AJAX
within a browser, there is AJAX engine
52
RESTful Pet Catalog Web Service
A d d r e s s ab le
R e s o u r c es
W e b C o n t a in e r
Server
Client
http://petstore/catalog/resources/items/
HTTP GET
{"url":"http://store/catalog/item1",{"url":"http://store/catalog/item2"}
Response JSON slide urls
53
Dojo Client
• Use dojo.xhrGet to make HTTP method call to catalog service to get JSON items data:
{"items": {"@uri":"http://host/catalog/resources/items/", "item":[ {"@uri":"http://host/catalog/resources/items/1/", "name":"Friendly Cat", "description":"This black and white colored cat is super friendly.", "id":"1", "imageurl":"http://localhost:8080/CatalogService/images/anthony.jpg"}, {"@uri":"http://host/catalog/resources/items/2/", "name":"Fluffy Cat", "description":"A great pet for a hair stylist! "id":"2", "imageurl":"http://localhost:8080/CatalogService/images/bailey.jpg"} ] } }
54
Getting Items from the RESTful Service
loadSlides: function (){ var targetURL = "resources/items/"; dojo.xhrGet({ url: targetURL, handleAs: "json", load: room.handleResponse, error: room.handleError }); },
handleResponse: function (responseObject, ioArgs){ if(!responseObject.item ){ return ; } ...
},
call url
Callback function
Response Data format
On error function
55
Example RESTful Catalog
56
Dojo client index.html
<button dojoType="dijit.form.Button" onclick="next"> Next</button>
<div id="grid" dojoType="dojox.Grid" model="model" structure="layout" autoWidth="true" >
http://weblogs.java.net/blog/caroljmcdonald/archive/2008/08/a_restful_pet_c.html
Grid widget model=data to display in grid
structure=layout for Grid
57
Dojo client.js formatImage = function(value) { if (!value) return ' '; return "<img src='" + value + "'/>"; };// Data Grid layout// A grid view is a group of columnsvar view1 = { cells: [ [ {name: 'Name', field: "name"}, {name: 'Description', field: "description"}, {name: 'Photo',field: "imagethumburl",
formatter: formatImage, }, {name: 'Price',field: "price"} ] ]};// a grid layout is an array of views.var layout = [ view1 ];// the model= collection of objects to be displayed in the gridmodel = new dojox.grid.data.Objects(null,null);
model=data to display in grid
layout for Grid
58
Dojo client.js // make request to the items web servicefunction loadTable(page){ start = page * batchSize; var targetURL = "resources/items/?start="+
encodeURIComponent(start); dojo.xhrGet({ url: targetURL, handleAs: "json", load: handleResponse, error: handleError });}// Process the response from the items web servicefunction handleResponse(responseObject, ioArgs){ // set the model object with the returned items list model.setData(responseObject.items.item); }function next() { page =page + 1; loadTable(page);}
Performs HTTPGET on url catalog/items
Callback puts response data in dojo model
for grid table
59
COMETCOMET
60
Comet:
Server
Client 1 Client 2
the server pushes data to the client over a long-lived HTTP connection
61
Ajax Push and HTTP keep-alive
Comet:
• server pushes data to the client over a previously opened connection
HTTP/1.1 Keep-Alive or Persistent Connection:
• keeps connection open until an explicit 'close connection' message or timeout Long Poll: Send a request to the server,
request waits for an event, then response sent
62
Ajax PushHTTP example
GET /slideshow/resources/slides
Accept: */*
Connection: keep-alive
Host: localhost:8080
Handshake
HTTP/1.1 200 OKContent-Type: application/json-comment-filteredServer: GlassFish/v3
/*[{"id":"0","minimumVersion":0.9,"supportedConnectionTypes":["long-polling","callback-polling"],"successful":true,"advice":{"reconnect":"retry","interval":0},"channel":"/meta/handshake","clientId":"3b37f0aae53ab2f1","ext":{"json-comment-filtered":true},"version":1.0}]*/
63
Blocking http request =server catastrophe
GET /updates HTTP/1.1Connection: keep-alive
GET /updates HTTP/1.1Connection: keep-alive
GET /updates HTTP/1.1Connection: keep-alive
GET /updates HTTP/1.1Connection: keep-alive
GET /updates HTTP/1.1Connection: keep-alive
64
GlassFish Grizzly CometNIO:
• non-blocking sockets
ARP Asynchronous Request Processing:
• Doesn't block a thread per http request
• availability of threads gives scalability
65
Introduction to Grizzly Comet
• Grizzly Comet is a framework that ship with GlassFish v1|2|3, and can also be embedded into any application using the Grizzly Embed interface (no fish involved).
• The Grizzly Comet Framework includes a set of components that can be used for building Comet based application:> Grizzly Comet, Continuation, Grizzlet, Messages Bus,
Bayeux support
66
Server-side Ajax Push: Who supports whatThe asynchronicity matrix.
XWebLogic
Container Asynchronous IO
Suspendible Request/Response
Delivery Guarantee
Jetty XTomcat X XGlassFish X X XResin X
67
The Bayeux Protocol
• http://svn.xantus.org/shortbus/trunk/bayeux/bayeux.html
• Bayeux is a JSON-based protocol for clients to register interest in events and for servers to deliver them in a more timely fashion than Ajax-based polling allows.
• With Bayeux, you only needs to write the client.
• The goals of the Bayeux spec so far have been to:> make event delivery fast> keep it simple> provide extension points in the protocol
68
Bayeux
HTTP Publish Subscribe
protocol for routing JSON-encoded events between clients and servers in a publish-subscribe model
Grizzly provides an implementation of Bayeux
Just configure Glassfishdomain.xmland Web App web.xml
69
Bayeux
Multiple Channels
Http
Comet and Reverse Ajax
Cometd clients
JSON Messages are published on specified channels
70
Bayeux/CometdJSON Publish/Subscribe
• JSON Messages are published on specified channels
• Channel operations: connect, subscribe, unsubscribe, etc.
• Multiple transports: polling, long-polling, iframe, flash
• Server-side just event bus for client side
[
{
"channel": "/some/name",
"clientId": "83js73jsh29sjd92",
"data": { "myapp" : "specific data", value: 100 } }
]
71
Enable Comet in GlassFish V2 Admin Console
72
Configure Cometd • Enabling Bayeux in GlassFish
> web.xml<servlet> <servlet-name>Grizzly Cometd Servlet</servlet-name> <servlet-class> com.sun.grizzly.cometd.servlet.CometdServlet</servlet-class> </servlet><servlet-mapping> <servlet-name>Grizzly Cometd Servlet</servlet-name> <url-pattern>/cometd/*</url-pattern></servlet-mapping>
73
Cometd
HTTP Requests
dojox.cometd●Dojo-based JavaScript client●Implementation of Bayeux Protocol
74
RESTful Web Services and Comethttp://developers.sun.com/appserver/reference/techart/cometslideshow.html
75
RESTful Slideshow Web Service
A d d r e s s ab le
R e s o u r c es
W e b C o n t a in e r
Server
Client
http://host/slideshow/resources/slides/
HTTP GET
{"url":"http://host/slideshow/image1.jpg",{"url":"http://host/slideshow/image2.jpg"}
Response JSON slide urls
76
Cometd Step1 : Initialize
dojo.require("dojox.cometd");
//Initialize a connection to the given Comet server: the GlassFish Grizzly Bayeux servlet
dojox.cometd.init("serverURL");
Comet Server
Client 1Client 2
77
Cometd Step 2: Subscribe
Client 1Client 2
dojox.cometd.subscribe(“topic”, "object", "callbackFunction");
• Subscribes the client to the topic channel
• Any time a message is sent to the topic channel
• the object's callback will be invoked
Comet Server
78
79
80
Cometd Step 3: Publish
Comet Server
Next sl ide url
dojox.cometd.publish("topic", {slide: url});
a client publishes the next slide url to the topic channel
JSON message
client 1
81
82
Cometd Step 4: Update Clients: CallBack Comet Server
Client 2 Client 3
callBackFunction(slideUrl){ slide.innerHTML ="<img src='" + slideUrl + "'/>"; ... }
●The callback function is called with the published message when a new message is received●This callback function updates the browser content
● html img tag with the slide url from the published message
Update Browser Update
Browser
83
84
Summary
• REST architecture is gaining popularity> Simple, scalable and the infrastructure is already in
place
• JAX-RS (JSR-311) provides a high level declarative programming model> http://jersey.dev.java.net> NetBeans 6.1 , 6.5 has wizards to help
• Dojo makes javascript easier• Dojo cometd with Grizzly makes building comet
apps easy
85
RESTful Web Services and Comethttp://developers.sun.com/appserver/reference/techart/cometslideshow.html
86
RESTful Web Serviceshttp://netbeans.tv/screencasts/offset/7/
87
Example RESTful Cataloghttp://weblogs.java.net/blog/caroljmcdonald/archive/2008/08/a_restful_pet_c.html
88
For More Information• Web 2.0 & ajax
> http://developers.sun.com/ajax/• Dojo
> http://dojotoolkit.org/• JAX-RS Reference Implementation
> http://jersey.dev.java.net/
• Glassfish> https://glassfish.dev.java.net/> http://blogs.sun.com/theaquarium/
• Cometd> http://cometdproject.dojotoolkit.org/
• Carol's Blog> http://weblogs.java.net/blog/caroljmcdonald/
●
–
89
Carol McDonald Java Architect
http://weblogs.java.net/blog/caroljmcdonald/