First Steps with RestLet 1.1RC2 in JDeveloper 11g – restful services 101

WebServices are hot. Some more so than others. SOAP based WebServices are frequently seen as not very lean and agile. Robust – perhaps. Widely supported – no doubt about it. Key element of almost any SOA infrastructure – sure. Easy, lightweight to deploy or to program a client against – no, not really. Inituitive? Bookmarkable? Addressable? – none of those. Restful web-services are the easy to use, lightweight, navigation oriented complement to the more heavy weight WS* SOAP based web services. REST is the natural extension of HTTP – leveraging a lot of its potential in a very direct way. REST services focus on Resources – that are searched & retrieved, created, updated and deleted. Resources can refer to each other – through hyperlinks that equal new REST service calls. The representation of Resources – the format of the response received or sent by a client has to be agreed upon; it usually is XHTML, XML or plain text.

Under JSR-311, a formal specification for REST is being developed, with project Jersey – nearing its completion – the reference implementation. An even more mature Java project for RESTful services is RestLet – a fairly easy to use library that allows for easy publication of Restful services. Its main job is interpreting the URIs in requests sent to the server/service and routing them to the appropriate resource handler and more particularly the right method depending on the nature – GET, POST/PUT, DELETE – of the HTTP request.

In this article I will demonstrate a very first introduction to the use of RestLet with JDeveloper 11g.....
Note: the example shown here is based on the tutorial published on the RestLet’s website.

Steps:

1) Open JDeveloper 11g. Create a new application, create a new project

2) Create a new JSP – accept all defaults (for example the name untitled1.jsp); the jsp is just a convenience to get our web.xml configured and to run/deploy the application on the embedded application server

3) download sources.zip and extract the three jar-files from the WAR file (com.noelios.restlet.ext.servlet_2.5.jar, com.noelios.restlet.jar, org.restlet.jar).Copy the jar files to a new directory lib under WEB-INF in the project. Add these three jars to the project.

First Steps with RestLet 1.1RC2 in JDeveloper 11g - restful services 101 rest019

4) create class RestfulApplication in package nl.amis.rest.controller. The class extends org.restlet.Application. This class will set up the various resources and the URLs that route to them. Well, for starters it will set up just a single resources (things) and one url (/things) that maps to this resource. The class also initializes a list of Thing objects, the pretty pointless resource that our REST service will expose.

package nl.amis.rest.controller;

import java.util.ArrayList;
import java.util.Collection;

import nl.amis.rest.resources.Thing;
import nl.amis.rest.resources.ThingsResource;

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


public class RestfulApplication extends Application {
public RestfulApplication() {
things.add(new Thing("FirstThing", "Wildlife in South America",
"American President", 2008, 42));
things.add(new Thing("OneMoreThing", "Officer Orange",
"Sixteen Degrees", 8, 305));
}

private Collection<Thing> things = new ArrayList();

/**
* Creates a root Restlet that will receive all incoming calls.
*/
@Override
public synchronized Restlet createRoot() {
// Create a router Restlet that defines routes.
Router router = new Router(getContext());

// Defines a route for the resource "list of things"
router.attach("/things", ThingsResource.class);

return router;
}

public void setThings(Collection<Thing> things) {
this.things = things;
}

public Collection<Thing> getThings() {
return things;
}
}
 

The Thing class referred to here is defined as follows:

package nl.amis.rest.resources;

public class Thing {

private String name;
private String someOtherProperty;
private String andThisToo;
private int importantValue;
private int thisValueAsWell;

public Thing() {
}
public Thing(String name, String someOtherProperty, String andThisToo, int importantValue, int thisValueAsWell) {
this.name = name;
this.someOtherProperty = someOtherProperty;
this.importantValue = importantValue;
this.andThisToo = andThisToo;
this.thisValueAsWell = thisValueAsWell;
}

public void setName(String name) {
this.name = name;
}
... and other accessor methods
}
 

The more interesting class ThingsResource is created like this:

package nl.amis.rest.resources;

import java.io.IOException;

import java.util.Collection;

import nl.amis.rest.controller.RestfulApplication;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;


public class ThingsResource extends Resource {

Collection<Thing> things;

public ThingsResource(Context context, Request request,
Response response) {
super(context, request, response);
// Declare the kind of representations supported by this resource.
getVariants().add(new Variant(MediaType.TEXT_XML));
things = getThings();
}

/**
* Returns a listing of all registered items.
*/
@Override
public Representation represent(Variant variant) throws ResourceException {
// Generate the right representation according to its media type.
if (MediaType.TEXT_XML.equals(variant.getMediaType())) {
try {
DomRepresentation representation =
new DomRepresentation(MediaType.TEXT_XML);
// Generate a DOM document representing the list of
// items.
Document d = representation.getDocument();
Element r = d.createElement("things");
d.appendChild(r);
for (Thing thing : things) {
Element eltThing = d.createElement("thing");

Element eltName = d.createElement("name");
eltName.appendChild(d.createTextNode(thing.getName()));
eltThing.appendChild(eltName);

Element eltDescription = d.createElement("description");
eltDescription.appendChild(d.createTextNode(thing.getSomeOtherProperty()));
eltThing.appendChild(eltDescription);

Element eltAndThisToo = d.crea teElement("andThisToo");
eltAndThisToo.appendChild(d.createTextNode(thing.getAndThisToo()));
eltThing.appendChild(eltAndThisToo);

Element eltImportantValue =
d.createElement("importantValue");
eltImportantValue.appendChild(d.createTextNode(Integer.toString(thing.getImportantValue())));
eltThing.appendChild(eltImportantValue);

r.appendChild(eltThing);
}
d.normalizeDocument();

// Returns the XML representation of this document.
return representation;
} catch (IOException e) {
e.printStackTrace();
}
}

return null;
}


/**
* Returns the collection of things managed by this application.
*
* @return the collection of things managed by this application.
*/
protected Collection<Thing> getThings() {
return ((RestfulApplication)getApplication()).getThings();
}


}
 

Note that this class extends org.restlet.resource.Resource. ThingsResource specifies in its constructor that it supports only the representation in TEXT_XML. Regardless of the specific wishes of a client, that format is all that is available for this resource. It then overrides the represent() method. This method is called to deal with a GET request. Other methods would be overridden to handle POST, PUT and DELETE. The represent method creates an XML document with a <things> root element and <thing> child elements, based on the contents of the things collection retrieved from RestfulApplication. Note that the XML document (fragment) is created inside a (RestLet) DomRepresentation object. When the document is complete, this DomRepresentation object is returned as the result from this method.

5) Configure web.xml

We need to ensure that all requests that try to access one of the RESTful Resources are handled by the RestLet Servlet. In our case that means all requests period. Therefore, we create a servlet mapping with a URL pattern consisting of the wildcard /*. The Restlet Servlet is configured through the context parameter org.restlet.application that is set in the web.xml. This parameter tells the servlet about the Application class to instantiate to learn about all resources and the url’s that lead to them. In our application that Application class obviously is RestfulApplication.

Add the following fragment to the web.xml file that was created when you created the untitled.jsp.

 <!-- Application class name -->
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>nl.amis.rest.controller.RestfulApplication</param-value>
</context-param>
<!-- Restlet adapter -->
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>com.noelios.restlet.ext.servlet.ServerServlet</servlet-class>
</servlet>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

6) To deploy and access the RESTFul services, run untitled1.jsp

When you run the JSP, the entire Web Application in our project gets deployed on the internal/embedded/integrated/associated (I do not know the exact term for the WebLogic container used for deployment from within JDeveloper 11g) WebLogic server. The JSP does not show up, as all requests are handled by the RestLet Servlet. However, the URL to the JSP is not one the servlet can route forward to a resource handler, hence the browser displays an error.

Now when we change the URL by replacing untitled1.jsp with things. Now we see the typical REST(ful) style URL: the name of the resource that is requested is contained in the URL. In fact, apart from host, port and application context root, the url only contains the name of the resource.

First Steps with RestLet 1.1RC2 in JDeveloper 11g - restful services 101 rest020

From this point onwards it is fairly easy to add another resource and/or add support for other operations besides GET. Let’s do the former and leave the latter for later.

Add the Thing resource

We would like to remove some of the details from the Things list shown above and only display them when the request comes in for the specific resource in a URL format like: host:port/application/things/{thingName}.

Our intent to support this url must be configured in RestfulApplication by adding this line:

router.attach("/things/{thingName}", ThingResource.class);

The ThingResource class referred to here has to take care of handling GET (and other requests eventually) for the Thing resource. The class can get hold of the requested {thingName} from the original request by checking the request parameters.

The class ThingResource:

package nl.amis.rest.resources;

import java.io.IOException;

import java.util.Collection;

import nl.amis.rest.controller.RestfulApplication;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;


public class ThingResource extends Resource {

Thing thing;


public ThingResource(Context context, Request request, Response response) {
super(context, request, response);
// Declare the kind of representations supported by this resource.
getVariants().add(new Variant(MediaType.TEXT_XML));
// get the thingName parameter from the URL /things/{thingName}
String thingName =
(String)getRequest().getAttributes().get("thingName");

// Get the items directly from the "persistence layer".
thing = getTheThing(thingName);

}

/**
* Returns a listing of all registered items.
*/
@Override
public Representation represent(Variant variant) throws ResourceException {
// Generate the right representation according to its media type.
if (MediaType.TEXT_XML.equals(variant.getMediaType())) {
try {
DomRepresentation representation =
new DomRepresentation(MediaType.TEXT_XML);
Document d = representation.getDocument();
Element eltThing = d.createElement("thing");
d.appendChild(eltThing);

Element eltName = d.createElement("name");
eltName.appendChild(d.createTextNode(thing.getName()));
eltThing.appendChild(eltName);

Element eltDescription = d.createElement("description");
eltDescription.appendChild(d.createTextNode(thing.getSomeOtherProperty()));
eltThing.appendChild(eltDescription);

Element eltAndThisToo = d.createElement("andThisToo");
eltAndThisToo.appendChild(d.createTextNode(thing.getAndThisToo()));
eltThing.appendChild(eltAndThisToo);

Element eltImportantValue = d.createEle men t("importantValue");
eltImportantValue.appendChild(d.createTextNode(Integer.toString(thing.getImportantValue())));
eltThing.appendChild(eltImportantValue);

d.normalizeDocument();

// Returns the XML representation of this document.
return representation;
} catch (IOException e) {
e.printStackTrace();
}
}

return null;
}


private Thing getTheThing(String thingName) {
Collection<Thing> things =
((RestfulApplication)getApplication()).getThings();
for (Thing thing : things) {
if (thingName.equalsIgnoreCase(thing.getName()))
return thing;
}
return null;
}
}
 

We can now access individual things when we know their name (/things/FirstThing):

First Steps with RestLet 1.1RC2 in JDeveloper 11g - restful services 101 jersey rest021

Resources

Download the JDeveloper 11g Application for this article: MyFirstRestFulService.zip.

The RestLet project’s homesite – it has just released the RestLet 1.1RC2

Quickstart with RestLet

One Response

  1. Narayana November 10, 2008