Jose Sandoval Google
 Resume     Book     Software     Drawings     Home     Subscribe to RSS feed Search Web Search josesandoval.com

REST in Java (Restlet demo)
Monday, September 29, 2008

Abstract: in this entry I talk about a REST example in Java using the Restlet framework. You can download the running application together with the source code.

I was looking for REST implementations for Java web servers and found a couple of descent APIs. The one I found the easiest to work with (for what I need) is the Restlet framework. It's very light, well documented, and it's open sourced.

The Restlet framework can be used in two modes: first, as a standalone web service (not discussed here, but very cool); second, as a Servlet extension (discussed here, and also very cool).

The framework's documentation has a couple of introductory examples, but the first one is too simple and the second one introduces an XML structure that confused me (yes, I'm easily confused). Therefore, I wrote this entry and its accompanying demo for my sake and anyone else looking into the Restlet framework.

My intention here is to create a simple REST application that is more realistic than the intro apps (I mean, how many "Hello, World!" programs can you write?). I have to warn you, however, that I will not discuss the benefits of using REST as a web service architecture; I will not fully discuss what REST is--I'm assuming you already know; and, finally, I will not explain how to use the full Restlet API--I only talk about the Servlet extension mode.

The application
As with any software application, we need to have requirements. In this case I define the following:
  1. We have 2 types of resources, HTML and PDF, that we need to access via a web server (this word resource will become clear as we go along).
  2. We want to access these resources using REST. For example, all HTML resources are to be accessed via the user friendly link of

    .../html/RESOURCE_ID

    Similarly, all PDF resources are to be accessed with

    .../pdf/RESOURCE_ID.
You may be wondering why I need to access these resources this way and not directly with a regular web address. The answer to this question falls under the why of REST and I said I wasn't going to fully discuss it. I should, at least, give you a small taste of the REST philosophy and only say that these resources don't necessarily exist as physical objects in specific locations. A resource can be built from many parts of a system at run time: a database or multiple web services, for instance.

Whenever I talk about REST I give the example of a news story. Think for a moment of a CNN news story: a story is not just an HTML file together with a few images; a CNN resource contains images, text, movies, polls, and related content that are being gathered from many different sources. When you request

cnn.com/news/2010-10-10/Obama/

you don't just want a web page, you want a complete resource.

So, what's the different between accessing a resource with this URI

cnn.com/news/2010-10-10/Obama/

and this URI

cnn.com/news/getStory.jsp?date=2010-10-10&topic=Obama

To the end user, there is no difference: as a reader you see the same story, and it obviously works, as we've been accessing data the web this way for more than a decade now. (Note that a reader could be another machine accessing this resource to do something with it, e.g., store it in a cache server.) To the software developer, however, the differences are many and come back to the essence software engineering. On the one hand, with the latter, you give away implementation details (in this case I made it a Java server app). On the other hand, if your implementation changes, any bookmarks or cache systems are immediately broken--say we go from JSP to ASP: our link now looks like

cnn.com/news/getStory.asp?date=2010-10-10&topic=Obama

Imagine, one letter change making such a big difference and breaking so many things.

Does REST care about implementation details? For a system designed with a REST architecture in mind the implementation details don't matter. REST serves resources and a request to

cnn.com/news/2010-10-10/Obama/

will always be a valid resource (given that it's coded correctly, of course). The implementation is hidden and it will always work no matter if the response is implemented in Java, C, C++, or pigeon carriers. A resource is a resource is a resource (assume Gertrude Stein cared about REST).

The software implementation
To make this application work in any Java web server with the Restlet framework, we need 6 things, which I break into steps below: (1) the HTML and PDF objects; (2) the Application, which is a derived Restlet class; (3) an HTML Resource, which is also a derived Restlet class; (4) a PDF Resource, which is the same as (3), except that it's specific to a PDF resource; (5) the web.xml modification needed to connect the framework to the Servlet engine; and (6), the required libraries that you will need to make everything work.

Step 1 - The HTML and PDF resources
For this demo, I have 1 HTML file and 1 PDF file. I separated this step here because these items don't have to be physical things on a server: they could be generated somehow. The somehow is up to the architecture of the system. Therefore, you must decide first how the resources need to be generated. For simplicity, I decided to make these resources actual files in the OS.

Step 2 - Restlets
The guts of a REST layer using Restlet is the derived Application class. I mean that you need to extend org.restlet.Application and override the Application.createRoot() method.

createRoot() creates a Router object with the context of the application (the context here is the object that points to the running web application). You can look up at the API for the full details of what a Router is. For this example, however, think of the Router object as the entrance to our resource serving layer.

Note the 3 lines of code:

Router router = new Router(getContext());
router.attach("/pdf/{itemName}", PDFResource.class);
router.attach("/html/{itemName}", HTMLResource.class);


We have 2 resource types: HTML and PDF.

We're telling the REST layer to access these items via the URI of .../pdf or .../html. {itemName} is a directive telling the code that it will be an id of some kind and it's assumed the resource class knows what to do with it: created it, read it, modified it, or deleted it.

The full implementation of my class looks like:
package com.josesandoval.rest;

import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.Router;

public class RestServiceApplication extends Application {

public RestServiceApplication(Context parentContext) {
super(parentContext);
}

@Override
public synchronized Restlet createRoot() {
Router router = new Router(getContext());
router.attach("/pdf/{itemName}", PDFResource.class);
router.attach("/html/{itemName}", HTMLResource.class);

return router;
}
}


Steps 3 and 4 - HTML and PDF Resources
The HTMLResource and PDFResource classes are where things happen.

A full REST implementation is one that lets resources to be accessed, created, modified, and deleted. In my case, to simplify things, I only need the access part; hence, my resources are not fully RESTful, as I only override one method of the Restlet framework: getRepresentation().

My HTMLResource class looks like:
package com.josesandoval.rest;

import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.FileRepresentation;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.Variant;

public class HTMLResource extends Resource {
private String itemName;

public HTMLResource(Context context, Request request,
Response response) {
super(context, request, response);

itemName = (String) getRequest().
getAttributes().get("itemName");
getVariants().add(new Variant(MediaType.TEXT_HTML));
}

@Override
public Representation getRepresentation(Variant variant) {
if (MediaType.TEXT_HTML.equals(variant.getMediaType())) {
return new FileRepresentation(
"/assets/html/" + itemName + ".html",
MediaType.TEXT_HTML, 3600);
}

return null;
}
}


Note that I'm getting the resources directly from the OS. The files live under the /assets/ directory. The PDFResource class looks exactly the same, except where the string 'HTML' is you find 'PDF' instead; and, of course, the MediaType.TEXT_HTML changes to MEDIA_TYPE.APPLICATION_PDF.

Step 5 - web.xml
With everything coded, I need a way to tell my web server to interact with the REST layer. The Restlet framework includes a Servlet hook up that you need to configure before deploying your app.

This hookup is a simple edit to your web.xml file. For my example, the file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!-- This is my Restlet application. -->
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>com.josesandoval.rest.
RestServiceApplication</param-value>
</context-param>

<!-- This should always be here for Restlet stuff. -->
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>com.noelios.restlet.ext.servlet.
ServerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>


Nothing surprising here. What's more, you can probably use this same web.xml file for your own applications, but you need to change the context-param element to look for your own Application class.

Step 6 - The required libraries
As you've seen, it's a very light layer because everything has been abstracted out and all the heavy lifting is already done for you. Therefore, your code needs the following 3 jar files:

org.restlet.jar
com.noelios.restlet.jar
com.noelios.restlet.ext.servlet_2.4.jar
(this is 2.5 for Restlet 1.1)

The Running app
There is more about the Restlet framework that I haven't covered; however, this example should give you a real taste of what it's like to implement a RESTful web service. This example can be extended to do real things. For example, your resources don't have to come from the OS in the form of a file. You could talk to other services to get these resources.

I hope you download the war file and play with the source code; you will have to change your file locations, but everything works right off the box.

And these are the RESTful calls of this demo:

http://www.sandoval.ca:8080/RestService2/html/jose

http://www.sandoval.ca:8080/RestService2/pdf/jose

A big disclaimer applies here: this example doesn't have any validation or error code handling. A real application has to have validation and error checking.


10:03 PM | 2 comment(s) |


No...Don't take the keyboard away


I'm sure these things will have a place in the market, but I can't see myself coding all day with no real keyboard. The "click-clack" helps me think, and I like cleaning the keys with a Q-tip...No, I'm not obsessive about it.

Apple's Brick, the computer with no keyboard (this is pure speculation, of course).



9:34 AM | 0 comment(s) |


Off-shore tech support...
Friday, September 19, 2008

Off-shoring technical support may result in customer dissatisfaction.

Last week I ordered a ThinkPad X200 directly from Lenovo, Canada. Unfortunately, Lenovo uses UPS for deliveries. I have to say here that I almost canceled my order when the salesperson told me they use UPS. I relented, and completed the order. Lets give the small company a chance.

A few minutes after I had placed my order, I received the typical email with my order number. About 4 or 5 days later I received an email telling me that my order had shipped. I said cool, but because of the problems I have with UPS not delivering to my building, how will I ever know when the computer is in my area?

The Lenovo email doesn't have a UPS tracking number, so I decided to call Lenovo and get it. This is when things got interesting: I made two consecutive calls to their toll free number 877 884 4659.

For the first call, I pressed 1, which is the option for order status reports. The phone call was answered immediately by a female representative. I asked for my UPS number and I was told that I needed to call after "some time" to find the number because the "systems were down." I asked, "what do you mean call after some time? Like a week some time?" The representative said, "no, not a week." I interjected and said "so some time like 30 minutes?" She said, "yes, that's right. Exactly 30 minutes." Grumble, grumble, fine.

Note that I didn't wait 30 minutes to make the next call.

For the second call, I decided to be clever and listen to all the options in the menu. Option number 6 is for sales. I pressed 6 and waited a few seconds. The phone was answered promptly and a male voice said: "how can I help you?" I said, "I need the UPS tracking number for my order." He said, "sure, what's your order number?" I gave it to him and he checked the system and said that it's shipped but it hasn't made into a truck yet. Fair enough. I'll call back next week for the number, as told to do so.

Hm? I thought the systems were down.

And I'm back to the beginning of my entry: one of those calls was off-shore; one of those calls left me dissatisfied.

It's hard to control quality, but such variance in service should be worrisome for Lenovo. If I didn't think ThinkPads are the best computers out there, I wouldn't waste my time with UPS or Lenovo's tech support. However, this time I had a good discount when I placed my order and I'm waiting for top of the line hardware: X200 - 2.4 GHz, 160 GB 7200 rpm drive, 4 GB DD3 RAM, 2 GB Flash RAM, latest Wi-Fi card, and Vista Business 64-bit (OK, this may not be wow factor, but it comes with it--I may, however, downgrade to XP: my package comes with it, too).

I can't wait to get my hands on my new toy...er...work machine.


9:12 AM | 1 comment(s) |


Hello, World!
Thursday, September 18, 2008

The most reliable program in the history of computers has to be the "Hello, World!" application. And I think it's reliable because it has been written so many times that it's almost impossible to screw it up.

Would you care to guess how many "Hello, World!" statements have graced computers screens?

I'm guessing millions. I'm also willing to bet my great-great grandchildren will be coding their first "Hello, World!" program in their first programming language classe, which will likely be in daycare at around age 2 or 3.

That reminds, me I should stop heading the ball on corner kicks: it's a bit tender today, after yesterday's game.


12:16 AM | 0 comment(s) |


They are funny...Really...
Thursday, September 11, 2008



11:35 PM | 0 comment(s) |


3, 2, 1...
Tuesday, September 09, 2008

.


11:33 PM | 0 comment(s) |


Music and a bad drawing connecting people
Sunday, September 07, 2008

This image mona4.jpg became the album cover for this album Simplicity on the far side of complexity.

Two continents apart. The web is interesting.


8:50 PM | 0 comment(s) |


Microsoft funny? Hells, yeah!
Friday, September 05, 2008

This is really funny. I'm not sure how effective it will be, though. I mean, some users are not so fond of the Vista OS, but the add campaign is already viral.



12:16 PM | 3 comment(s) |


Google Chrome looks good
Tuesday, September 02, 2008

Google's web browser looks good and it seems to be stable. So far no crashes, but it doesn't have a menu toolbar. This could be good and bad. I for one, miss the "Aft-F-C" shortcut to close a tab. I'm used to it and I don't like to use the mouse all the time.

I guess google still has some work to do. Nevertheless, you should download it, just to keep the browser wars alive.



5:18 PM | 3 comment(s) |


This page is powered by Blogger. Isn't yours?

Guestbook
© Jose Sandoval 2004-2009 jose@josesandoval.com