Search This Blog

Friday, April 25, 2008

REST Web Service Example with Restlet, Spring and Maven...

Time for me to blog something of technical interest again. Ever since I have
joined Overstock.com, I have found myself working with two new technologies, REST and
MAVEN. By no means do I consider myself an expert on the same but feel that
sharing some of my experience might prove beneficial to someone else.

A Restlet 2.0 Example is available in a later POST I would however recommend a read of this one before proceeding to the 2.0 example.

Clearly, I cannot share any OSTK proprietary work...

First some words about Maven. I have always wanted to use Maven even during
my career at PRFT. Sadly, I didn't get to it. Maven is not another ANT, it
so much more. Ever since I have started using Maven, I cannot find myself
not using it when possible.

Noting a few maven terms (some coined by me others maybe not ;-)):

1. Maven Repository:

A Maven repository is a public/private site that hosts different libraries
or jars.

2. Artifact Coordinates:

Every jar in a Maven repository can be identified by coordinates. For example,
if one is trying to find spring-2.5.1.jar, the artifact is represented as:

<groupid>org.springframework</groupid>
<artifactid>spring</artifactid>
<version>2.5.1</version>


Think of group Id as being a top level folder that aggregates multiple artifact
types. An artifact Id describes a particular artifact in the group and the
version helps identify the version of the artifact.

3. Local Repository:

Maven downloads artifacts and places them in your $HOME/.m2 folder. Thus, you
always maintain a copy of the jar, i.e., a nicely shelved away via version. Thus the jar will not
be downloaded all the time but only once.

4. POM:

The foundation of maven lies in what is known as a POM or
Project Object Module. When using Maven, you will often find files titled
pom.xml. These pom files describe your project for you. A Maven project
can serve as an 'Aggregator' project that serves to group children project
under one umbrella. These project are typically called "Multi-Module" projects.

5. Maven Eclipse Plugin:

I use the Q4E Maven Eclipse plugin. Its pretty nice but not yet perfect. With the plugin, I am able to import the different maven projects into eclipse. The visual dependency management feature of this plugin is awesome.

6. Maven Archetype:

An Archetype is a template for creating projects in its likeness. There are different archetype available, for example an archetype to create a J2EE EAR project, a Web Project, a simple java project and App fuse projects as well.

Enough about Maven, a bit about REST!

I am not planning on entering into a REST versus SOAP or what is REST
discussion here but merely wanting to demonstrate a Web Service that uses
REST and Maven.

The stir created by Roy Fieldings dissertation has opened multiple discussions
and thoughts regarding how the Web should be viewed.

An implementation of REST concepts in Java was facilitated by the RESTLET project pioneered by Jérome Louvel.

One of the core classes of the RESTLET framework is the Resource class. Resources tend to represent exactly what their name means, a resource! For example, an Order Resource that
represents Order related data, a Product Resource that represents Product
information etc. I would like to talk more about REST and the RESTLET project
but the posting would be too verbose...maybe a later post.. One can get a good understanding of the RESTLET project via their documentation and starter examples.

Onto the example:

The example demonstrates a simple Restful Web service developed
using Restlet + Spring Framework + JaxB + JSON + Maven + Dozer + JUnit + EasyMock.

The project is organized as follows:


SpringTest
.
-- client

-- common

-- integration-test

-- service

`-- webapp


1. Spring Test:
The Web Service project is a multi module Maven Project. The SpringTest project
is the root level aggregator project that aggregates the modules such
as common, client, service, integration-test and webapp.

2. common:

The common project contains the code that is shared by other modules
of the web service project. It contains the DTO (data transfer objects), common
exceptions, utilities etc.

3. client:

The client project represents the Webservice client code. This project is
pretty much a wrapper around the Restlet API so that consumers of the service
have an easy way to communicate with the web service without having to
concern themselves with specifics of the web service.

4. service:

The service project represents the heart of the web service. The
service is not mixed in with the webapp project as the business logic is
not necessarily tied to RESTLET or REST. If required in the future, a
SOAP or EJB version of the web service could be exposed by re-using the code
from the service project.

The domain model is included in the service project itself. The reason for
the same is; in many cases the model and the service go hand in hand. Now, it
could be argued that the model could be placed in a separate maven module for
re-use. That IMO should be the direction should the model appear to be
re-usable. Also note that the model need not necessarily translate to what
is transferred via the web service. I am therefore making a separation of the
model and the DTO. There is clearly no one size fits all here and depending
on the scope of the project, making the model and the DTO one and the same
might be an option.

5. integration-test:

The project contains a test which will perform end to end integration test.
When an integration test is run, a Jetty Server instance is started using
Cargo and the webapp is deployed onto the server. Then the integration test
is performed which will communicate with the server to assert that the
web service contract is valid and the server will ensure that it performs
as expected. My reason for using Cargo is that one could easily switch to a
different container for testing if required.

Note that one could have additional integration test projects defined when the service
undergoes an upgrade and there is a need to maintain backward compatibility with the Web Service clients.

What does the example do?
The example is a simple mock of an order system. One can get a list of
Products supported by using the Product Service. The Product Service
uses JSON for its transport (just to demonstrate). The Order Service
can place an order, update an order, query an order and delete and order.
The Order Service uses JAXB for marshaling its data.

Standard REST concepts like POST, PUT, GET and DELETE are explored by the
example. I don't believe that I have 100% conformity with REST concepts in the example :-)

The example is a 'simple' one in all senses of the word. Thread safety,
exceptions etc are not even considered. One could easily incorporate the
same if developing a real world web service.

The Project uses Spring as a DI container. Rest Resources are injected with
dependencies using Spring auto-wiring.

Running the example:

1. JDK 1.5.X or Greater:
Ensure you have jdk1.5.X+ installed. The code uses annotations extensively.
From your command line, when issuing a "java -version" make sure that
it is greater than or equals to 1.5.X.

2. Maven Install:

Download Maven and install it. If on a *Nix environment, install maven at
/opt/. Ensure that maven is available in your PATH. What this means is if
you execute a "mvn -version" you should see details of your installation. Additionally, ensure you obtain a 2.0.x version of maven.

3. Eclipse Install:

Download and install an eclipse distribution. Eclipse is not required to run the examples but helps in viewing editing the code.

4. Q4E Maven Plugin:

Open eclipse and install the Q4E Maven plugin. Note that you might need to point the plugin to your maven installation.

5. Download Example:

Download and extract the SpringTest.zip project using your favorite archiving tool. The example has been tested with Restlet 1.1-M4 and Java Version 1.5.X and 1.6.X. If you would like to use a version that uses the API's from Restlet 1.1-M2, then the same can be obtained from HERE.

6. Import into Eclipse:
Import the modules into eclipse as Maven projects. Again this step is optional. It is required if you would like to view the project.

7. Installing Modules:
From the command line, issue a "mvn install" from within the
SpringTest project. What this command does is installs the maven modules in your local repository. As part of the process it will execute JUnit tests and integration tests.

8. An Integration Test:

Run a "mvn integration-test" from the SpringTest folder to see the
integration test in action.

8. Debugging the Web App:
Alternatively, you can watch the project in action by starting jetty
from the webapp project and debugging via remote server attach.

You will need to start jetty from the webapp project using "mvn jetty:run" and then do a remote server attach from eclipse. Ken Steven's blog has a pretty nice description as to how to do the same.

If you have difficulties executing the project, ping me...;-).. Once again the code for the example is available HERE.

The very same example that uses JAXRS (JSR 311) is described HERE.