Create, Read, Update, and Delete (CRUD) With Jersey RESTful Web Services

Introduction

In a previous article I explored how to create a Java web application that uses Jersey to create a RESTful web service. The example application allowed the user to RSVP for a party online. The RESTful web service provided two services: one that returned an XML document with all RSVPs as xml nodes and another that added an RSVP using an XML node sent by the client. If you've not read the previous article, you should do so to better understand this one.

That example application is missing a few features common to a CRUD (create, read, update, and delete) application. The application allows the user to create an RSVP and to read the complete list of RSVPs, but there is no update, delete or read a specific RSVP functionality. To demonstrate how you can use Jersey to create a RESTful web service that provides those services, I've created a new version of the application with an administrator page. On the administrator page, a user can find (read) a specific RSVP, update an existing RSVP, and delete an RSVP.

Example Application

You can download the example application here. The download is an archived Eclipse - Maven project. You can view a working example here.

To load the project into Eclipse, just do File - Import - Existing Projects into Workspace (under General folder), click Next. Click on the Select Archive file radio button and click on the browse button. Navigate to where you downloaded the above archive (.zip file), select RSVPCrudApp.zip and click Open. You should see RSVPCrudApp under the projects window. Click Finish. Maven will download any jars specified as dependencies and Eclipse will rebuild the project.

I use Tomcat 6 as my Java web application container. To run the example application using Tomcat, do the following: In Eclipse click on the project name then select Run - Run As - Run on Server. Configure your Tomcat 6 server if you've not previously done that. Eclipse will start up Tomcat and then open a web browser with the default home page loaded (http://localhost:8080/RSVPCrudApp/index.html).

You can also run the example application using Maven and Jetty. Open a command window and navigate to the project's root folder (for example: c:\restful_projects\RSVPCrudApp\"). Then type mvn clean and then mvn jetty:run. Once you see [INFO] Started Jetty Server in the command window, open a web browser and go to this URL: http://localhost:8080/RSVPCrudApp/index.html). There is a link to the administrator page (admin.html) on the index.html page.

To stop the Jetty server just type ctrl-c in the command window.

If you don't use Eclipse, you can unzip the download and copy the source files to your own IDE.

Read A Single RSVP

On the administrator web page (admin.html) the user sees a form where he/she may enter a name. When the user clicks on the Find RSVP button the JavaScript function findRSVP is executed.


function findRSVP() {

//put name value in the path
var namePath = $('name').getValue();
new Ajax.Request('/RSVPCrudApp/services/rsvpservices/'+namePath,

...

}

The one thing to note is that the function gets the value the user entered in the form's name input field and then appends that value unto the URL that is used to make the Ajax request. (NOTE: See the previous article for a discussion about the use of the Prototype JavaScript library and its Ajax object). For example, if the user typed "Bruce" into the name field then the URL would be "/RSVPCrudApp/services/rsvpservices/Bruce"

In the Java class that Jersey will convert to a RESTful web service, RSVPResources.java, is this method:


@GET
@Path("{name}")
public RSVP getRSVP(@PathParam("name") String name) {

RSVP foundRSVP = null;

for (RSVP rsvp : rsvpMap.values()) {

if (rsvp.getName().equals(name) ) {

foundRSVP = rsvp;
break;
}

}//end for

return foundRSVP;

}//end method getRSVP

The above method will respond to the URL with path of "/RSVPCrudApp/services/rsvpservices/Bruce". The method's parameter will be given the value of the part of the path that is after /RSVPCrudApp/services/rsvpservices/. So in this example the parameter's value is "Bruce". (NOTE: see the first article in this series on Jersey RESTful web services for more detail on the @Path and the @PathParam annotations).

The getRSVP method just searches through the RSVP objects stored in the collection and finds the first one that matches the provided name. (Of course this method wouldn't be what you'd want to use if two or more people could have the same name). The method returns the RSVP object, which Jersey and the JAXB libraries converted into an XML node and the XML is returned to the client.

Back in admin.html, the response received from calling this method of the web service is displayed to the right of the search form and includes two links: edit and delete. For example: Bruce is attending. (Edit | Delete)

Update An RSVP

The user can click on the edit link (see above) to update an RSVP. Clicking on this link will call the openEditForm JavaScript function (see admin.html) which will set the value of the edit form fields to the values of this RSVP and then make the form visible. The user can then make any changes and click on the Update RSVP button.

Clicking on the UpdateRSVP button calls the JavaScript function updateRSVP. This function gets the values the user entered in the edit form and then creates a XML rsvp node. The function then calls another JavaScript function, ajaxUpdateRSVP passing that function the XML rsvp node.

The JavaScript function ajaxUpdateRSVP uses Prototype's Ajax object's Request function to call the following URL: "/RSVPCrudApp/services/rsvpservices/update" as a post request and the post request's body is the XML rsvp node.

This method from class RSVPResources will process that request from the client.


@POST
@Path("update")
@Produces("text/html")
@Consumes("application/xml")
public String updateRSVP(RSVP rsvp) {

rsvpMap.put(rsvp.getId(), rsvp);
return "RSVP updated. " + rsvp.toString();

}//end method addRSVP

The method just replaces the RSVP object stored in the collection that has the same id value as the provided RSVP object (JAXB and Jersey converted the XML sent by the client into an RSVP object).

See the previous article for a discussion on how a post request that has an XML body (payload) is processed.

Delete An RSVP

When the admin user searches for an RSVP and the JavaScript displays the result, there is a link to Delete that RSVP (see above). Clicking on the Delete link, calls JavaScript function deleteRSVP and passes to the function the id value of the RSVP the admin user wants to delete.


function deleteRSVP(id) {
    
//alert("deleting id " + id );
new Ajax.Request('/RSVPCrudApp/services/rsvpservices/delete/'+id,
    
...

}

Note that the JavaScript function appends the id value to the path: "/RSVPCrudApp/services/rsvpservices/delete/". So if 1 was passed to the JavaScript function the URL called by the Ajax.Request would be "/RSVPCrudApp/services/rsvpservices/delete/1".

In the RESTful web service class, RSVPResources.java, there is this method, which will process the URL that includes delete and the id number.


@GET
@Path("delete/{id}")
@Produces("text/html")
public String deleteRSVP(@PathParam("id") int id) {

rsvpMap.remove( id );

return "RSVP deleted";

}//end method deleteRSVP

The id number will be used as the value for the method's id parameter. The method just removes from the collection the RSVP object with that id value.

Testing A RESTful Web Service

As I was developing the Java class that Jersey converts to be a RESTful web service, I did some research on how you can test the methods of the web service class. I found some information about the Jersey test framework, which is provided with the Jersey library. If you look at class RSVPResourceTest.java in package name.brucephillips.rsvpapp.test you can see how I used this framework to test some of the web service's methods.

The test runs fine using Maven and it appears that the Jersey test framework provides capabilities to create sophisticated tests of the Jersey RESTful web services. However, I wasn't able to find much information about how to use the framework so if you know of some goods posts about the Jersey test framework please comment below.

See this blog article for newer information about how to test a RESTful Web Service that uses the Jersey framework:
/blog/index.cfm/2009/9/14/Unit-Testing-Jersey-RESTful-Web-Services-That-Also-Use-The-Spring-Framework

Summary

This article described how to implement a simple CRUD application using a Jersey RESTful web service. The simple example application does not address some important design considerations such as form field validation on both the client and the server, handling exceptions and returning error messages to the client, and persistent storage of the RSVP objects. The example also doesn't illustrate the use of HTTP protocols PUT and DELETE to put a new record or delete a record. Rather this example just use the POST protocol to achieve that functionality.

The example application should give you an idea of how you can build and use a RESTful web service using Jersey. Jersey can be used for much more, so consult the references below to learn about Jersey and RESTful web services.

References

  1. Example Application - Archived Eclipse - Maven Project
  2. Example Application On bpjava.net
  3. An Introduction to Creating RESTful Web Services Using Jersey and Java, Bruce Phillips Blog
  4. An Example of Using Jersey RESTFul Web Services, Java, Ajax, and JavaScript, Bruce Phillips Blog
  5. JAX-RS, the Java API for RESTful web services
  6. jsr311-api 1.0 API
  7. Jersey, Sun's Reference Implementation for JAX-RS
  8. RESTful Web Services Developer's Guide, Sun MicroSystems
  9. Jersey Test Framework, Naresh's Blog
  10. Prototype JavaScript Library

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Hi Bruce,

its good to know that you could get your tests running with maven using the Jersey Test Framework.
But you also mentioned that you need some more information on the framework's usage. Could you please let me know what your requirement is? I'll see how the framework could be used for the same.

-Naresh
# Posted By Naresh | 6/9/09 1:44 AM
Naresh:

There are two items I was looking for.

1. The API for the test framework. The link for the Jersey API that posted on the Jersey wiki (http://wikis.sun.com/display/Jersey/Main) is for Jersey 1.0.3. I couldn't find in that API the com.sun.jersey.test.framework packagae.
In the examples that used the test framework, I got just a little lost by the method chaining:

ClientResponse response = webResource.path("data").type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);

The API would be very helpful in learning what each of these method calls does and what the parameters are for.

2. A tutorial article on how to use the test framework to write tests for common web service (e.g. CRUD) methods with a complete example. Studying the example code is somewhat helpful but I think a new user (someone new to Jersey and RESTful web services) could use a complete tutorial that walks him/her through how to write tests using the framework in an easy to follow example. Something like here is the getPerson method of our web service and here is how we can test this method using the test framework. You walk the user through building a web service method and then building the test (or even better build the test first and then the method that will pass that test).

That said the more I study the example code the more I see ways to use the test Framework. The Jersey test framework can be a huge part of developing RESTful web services.
# Posted By Bruce | 6/9/09 6:37 AM
One reason for the missing JavaDocs is because we are still in the process of improving the test framework support, but I shall see how we can get the javadocs for the framework be integrated in the Jersey javadocs.

As for the tutorial, I thought the Jersey samples would help learning the framework's usage. But I see that your point of the need of a separate tutorial is a valid one. I shall soon add a blog entry which walks through the framework's usage from scratch.
# Posted By Naresh | 6/10/09 12:58 AM
Another good one. I'm enjoying the series so fat. Nice job.
# Posted By jack | 11/10/10 12:57 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner