From the command line, after editing your ivy.xml, you must execute zero resolve from your application’s root directory.. When WebSphere sMash needs to find a file in the application, it l
Trang 1Figure 3.1 My Repository
After you have added the zero.resource module as a dependency to your application,
you must resolve your application “Resolve” is an Ivy term that means, “find all of my
applica-tion’s dependencies.” In AppBuilder and Eclipse, the resolve step happens automatically when
you add the dependency to your application From the command line, after editing your ivy.xml,
you must execute
zero resolve
from your application’s root directory The resolve command attempts to find the
zero.resource module in your local repository If it can’t find it, you get an error message and
are instructed to run zero update instead When you run zero update, the command finds the
appropriate zero.resource module in the remote repository and downloads it The application
is resolved once the download is complete When your application is resolved, it can make use of
the ZRM libraries
on My Repository (see Figure 3.1) When searching for the remote file, specify “zero” as the
organization and “zero.resource” as the module
Trang 2Virtual Directories
An important feature of WebSphere sMash’s dependency system is the concept of virtual
directo-ries When an application starts up, a virtual directory of the application and all of its
dependen-cies are created When WebSphere sMash needs to find a file in the application, it looks in the
application’s directory first, followed by the same directory in each of the application’s
depend-encies For example, if an HTML file in the application’s /public directory attempts to load the
file library.js from the server, WebSphere sMash’s static file server first looks in the
applica-tion’s /public directory If it can’t find the file there, it looks in the /public directory of all of
the dependencies until the file is found
Synchronizing a ZRM Model
As part of dependency resolution for the zero.resources module, the WebSphere sMash command
line within your application is enhanced with some new features The new commands added by
the zero.resource dependency take this form:
zero model <subcommand>
You can execute
zero model help
within your app’s root directory to see a list of the subcommands (duplicated here for your
con-venience):
dumpdata Dumps data from the ZRM database into files
loaddata Loads data from specified files into the ZRM
database reset Restores the ZRM database to the initial state
sql Writes the SQL that manages the database
arti-facts sync Create database artifacts and load initial
data
The command that we are interested in at the moment is sync The sync command
synchro-nizes the model with the database From a WebSphere sMash command-line interface in your
application’s directory or from the command prompt in the App Builder, execute the following:
zero model sync
This command creates database tables from the bookmarks.json model file and
popu-lates the tables with data from the initial_data.json file should it exist By default, the
tables are created using an embedded Derby database
Trang 3Event Handling in Groovy
We now have a database that reflects our model and contains some interesting data So, how do
we get a REST interface to our data? We have to create a resource handler We mentioned
han-dlers previously “Handler” is a WebSphere sMash term for a piece of code that responds to
events within the application’s lifecycle A handler that responds to HTTP requests for resources
is called a resource handler
Resource handlers, by default, are put into the /app/resources directory Handlers can
be written in Groovy, PHP, or Java For writing simple handlers, Groovy is hard to beat Because
Groovy is a scripted language with minimal syntactic overhead, you can write very concise
han-dlers In fact, our first handler is going to have a single, short line In your application’s
/app/resources directory, create a file called bookmarks.groovy In the file, put this line:
ZRM.delegate()
This line tells ZRM to handle all requests for the “bookmarks” resource, by filename
con-vention We don’t need to declare any imports The dependency resolution step we performed
earlier let Groovy know where to find the ZRM libraries
ZRM.delegate() is set up to handle the five LCRUD requests for our bookmarks
resources LCRUD is CRUD with an additional (L)ist semantic With this one line, we are now
able to process GET, PUT, POST, and DELETE requests for our bookmarks Let’s try it out
Running the Application
You can start your bookmarks application as described in the last chapter We haven’t done
any-thing to create a client yet, but we can use the browser to interact with some of our new REST
APIs From your browser, browse to the following:
http://localhost:8080/resources/bookmarks
This URL issues a GET request to the bookmarks resource handler Because “bookmarks” is a
resource collection, it performs a “List” on the bookmarks resources The results vary by browser,
but you will either see the response displayed in the browser or be asked to save the response as a file
The result is a compact JSON-format representation of the bookmarks resources If you would like a
more human-readable result, you can edit your config/zero.config file and add the following line:
/config/json/prettyPrint=true
Note that there is no need to restart your application Most configuration changes are
detected on the next client request Simply repeat the request for the bookmarks resource, and
you get a response that looks like Listing 3.4
Trang 4Listing 3.4 Bookmarks Response
[
{
"url": "http://www.ibm.com",
"name": "IBM",
"category": "Software Companies",
"id": 100,
"updated": "2008-12-18 00:30:29"
},
{
"url": "http://projectzero.org",
"name": "Project Zero",
"category": "Development",
"id": 101,
"updated": "2008-12-18 00:30:29"
},
{
"url": "http://groovy.codehaus.org",
"name": "Groovy",
"category": "Development",
"id": 102,
"updated": "2008-12-18 00:30:29"
}
]
From the response, we can see that the ID of the first entry is 100 Note that the IDs were
automatically created when the initial_data was populated We can now request individual
resources by using the ID in the URL, as follows:
http://localhost:8080/resources/bookmarks/100
This URL issues a GET (“Retrieve”) request and returns Listing 3.5
Listing 3.5 Bookmark GET Response
{
"url": "http://www.ibm.com",
"name": "IBM",
"category": "Software Companies",
Trang 5Figure 3.2 Posting with Poster
If you’d like to try out the REST APIs using the browser, you can use the “Poster” Firefox
Add-on (https://addons.mozilla.org/en-US/firefox/addon/2691) To create a new bookmark, you issue
a POST using values like those shown in Figure 3.2
To modify a bookmark, you specify the ID of the bookmark in the URL The Action would
be PUT, and the content would include all the nongenerated fields, as shown in Figure 3.3
To delete a resource, specify the bookmark ID in the URL and set the Action to Delete No
parameter body is needed
Explicit Event Handling
In the preceding example, we took the “happy path” and let ZRM handle everything for us Of
course, there are situations where we need more control You may need to handle your own GET,
PUT, POST, and DELETE requests For example, what if your REST interface needs to store the
data in a file or a legacy database? In that case, we would need to implement our resource handler,
bookmarks.groovy, using a pattern similar to Listing 3.6
Trang 6Figure 3.3 Putting with Poster
Listing 3.6 Resource Handler for Explicit Event Handling
def onList() {
// Retrieve the list of bookmarks from the
// data store and put into a java.util.Map
def bookmarks =
// Create the response
request.status = 200
request.json.output = bookmarks
request.view = 'JSON'
// The render method tells Zero to render
// the output using the JSON renderer
render()
Trang 7def onCreate() {
// Use the WebSphere sMash JSON decoder to
// decode the JSON-formatted bookmark
// request.input[] is a short-hand reference
// to the input data stored with the request
// in the Global Context The Global Context
// stores application state
def jsonBookmark = zero.json.Json.decode(request.input[])
// Create the id for the bookmark entry and
// add the entry to the data store
def bookmarkId =
def data =
// Set a response header in the request object in the
// Global Context
request.headers.out.Location = getRequestedUri(false) + '/' +
\ bookmarkId
// Set the HTTP response code
request.status = 201
request.json.output = data
request.view = 'JSON'
render()
}
def onRetrieve() {
def bookmarkId = request.params.booksmarksId[]
// retrieve the bookmark from the data store based on the id
def data =
// Create the response
if (data) {
request.status = 200
request.json.output = data
request.view = 'JSON'
render()
}
else {
// Not found
request.status = 404
Trang 8}
}
def onUpdate() {
def bookmarkId = request.params.bookmarksId[]
// Retrieve the requested bookmark from the
// data store based on the Id
def data =
// Update the data in the data store
// Set the response code
request.status = 204
}
def onDelete() {
def bookmarkId = request.params.bookmarksId[]
// Delete the entry based on the Id
// Set the response code
request.status = 204
}
The preceding example shows five methods: onList, onCreate, onRetrieve,
onUpdate, and onDelete These five methods define the convention for a resource handler You
don’t need to have your handler inherit from a parent class; you just need to implement these
methods By implementing these methods, you have complete control over how the requests are
processed
Event Handling in PHP
WebSphere sMash also supports PHP, of course PHP makes a fine alternative to Groovy for writing
resource handlers For ZRM-based resource handlers, use the dependency zero.resource.php
rather than zero.resource:
<dependency org="zero" name="zero.resource.php"
rev="[1.0.0.0, 3.0.0.0["/>
For our resource handler, we create /app/resources/bookmarks.php with the
Trang 9Listing 3.7 PHP ZRM Resource Handler
<?php
zrm_delegate();
?>
If we want to handle events individually in PHP, we need to create a class with the same
name as the resource in our resource handler file (with capitalization) So, for bookmarks.php, we
would do something like Listing 3.8
Listing 3.8 Explicit Event Handling in PHP
<?php
class Bookmarks {
function onList() {
// Retrieve the list of bookmarks from the data store
$bookmarks =
// build the response
zput('/request/status', 200);
zput('/request/view', 'JSON');
zput('/request/json/output', $bookmarks);
// The render_view method tells WebSphere sMash to render
// the output using the JSON renderer
render_view();
}
function onCreate() {
// Use the WebSphere sMash JSON decoder to
// decode the JSON-formatted bookmark
$bookmark = json_decode($HTTP_RAW_POST_DATA);
// Create the id for the bookmark entry and
// add the entry to the data store
$bookmarkId =
$data =
// Set a response header in the request object
// in the Global Context
$location = get('/request/path') "/" $bookmarkId
zput('/request/headers/out/Location', $location);
zput('/request/headers/out/Content-Type', 'text/json');
echo json_encode($data);
Trang 10zput('/request/status', 204);
}
function onRetrieve() {
$bookmarkId = zget("/request/params/bookmarksId");
// retrieve the bookmark from the data store based on the id
$data =
// If data is found, create the response as JSON
if (isset($data)) {
zput('/request/headers/out/Content-Type', 'text/json');
echo json_encode($employeeRecord);
zput('/request/status', 200);
} else {
// Page not found
zput("/request/status", 404);
}
}
function onUpdate() {
$bookmarkId = zget("/request/params/bookmarksId");
$bookmark = json_decode($HTTP_RAW_POST_DATA);
// Retrieve the requested bookmark
// from the data store based on the Id
// Update the data in the data store
// Set the response code
zput("/request/status", 204);
}
function onDelete() {
$bookmarkId = zget("/request/params/bookmarksId");
// Delete the bookmark from the data store based on the Id
// Set the response code
zput("/request/status", 204);
}
}
?>