Wednesday, January 21, 2009

Using RESTClient with Java's HttpServlet

I previously blogged about using RESTClient with the Sun JVM-provided HTTP Server. As I stated in that blog posting, I intend to use these tools to demonstrate HTTP and REST concepts at Rocky Mountain Oracle Users Group (RMOUG) Training Days 2009. I also intend to use the tried and proven Java HttpServlet in this presentation.

When I started using the Java servlet back in 2000, I read about the HttpServlet methods that correspond to the significant HTTP methods, but I didn't really override any methods in the majority of my servlets other than doGet and doPost. Looking back on the early servlet-focused books and articles, it is not surprising that this was the case because these materials focused on those two methods as well.

Although the Javadoc-based API information for Java EE 5 briefly discusses alternative methods in HttpServlet that can be overridden, many tutorials available even today focus on doGet and doPost. For example, the highly useful Java Servlet API Tutorial has an HTTP Support section that mentions the other methods but focuses on doGet, doPost, doHead. Similarly, the Java EE 5 Tutorial (PDF) also focuses on use of the HttpServlet's doGet method.

Roy Fielding's REST dissertation has been a significant catalyst in motivating many of us to think about HTTP differently. Specifically, we are now more inclined to think about the other methods supplied with HTTP. While many tools and browsers do not provide great support for all the major HTTP methods, the Java servlet has provided this support for some time and is an excellent mechanism for implementing and simulating operations that take advantage of the major HTTP methods.

It is very easy to take advantage of HttpServlet's support for major HTTP methods. This is demonstrated in the next code sample for the Java servlet class SimpleHttpServer.java:

SimpleHttpServer.java


package dustin.flex.rest;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
* Simplistic Java EE server-side application intended for demonstration of
* HTTP methods often use in REST-based applications.
*
* @author Dustin
*/
public class SimpleHttpServer extends HttpServlet
{
/**
* Servlet method responding to HTTP GET methods calls.
*
* @param request HTTP request.
* @param response HTTP response.
*/
@Override
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws IOException
{
final PrintWriter out = response.getWriter();
out.write("GET method (retrieving data) was invoked!");
}

/**
* Servlet method responding to HTTP POST methods calls.
*
* @param request HTTP request.
* @param response HTTP response.
*/
@Override
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws IOException
{
final PrintWriter out = response.getWriter();
out.write("POST method (changing data) was invoked!");
}

/**
* Servlet method responding to HTTP PUT methods calls.
*
* @param request HTTP request.
* @param response HTTP response.
*/
@Override
public void doPut( HttpServletRequest request,
HttpServletResponse response ) throws IOException
{
final PrintWriter out = response.getWriter();
out.write("PUT method (inserting data) was invoked!");
}

/**
* Servlet method responding to HTTP DELETE methods calls.
*
* @param request HTTP request.
* @param response HTTP response.
*/
@Override
public void doDelete( HttpServletRequest request,
HttpServletResponse response ) throws IOException
{
final PrintWriter out = response.getWriter();
out.write("DELETE method (removing data) was invoked!");
}

@Override
public String getServletInfo()
{
return "Server-side application demonstrating HTTP methods.";
}
}



This class can be referenced in the Java EE web descriptor file (web.xml) as shown next.

web.xml


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

<display-name>Simple Servlet Example Demonstrating Http Method Support</display-name>
<description>Demonstrates HttpServlet Support of HTTP Methods</description>

<servlet>
<servlet-name>SimpleHttpServer</servlet-name>
<servlet-class>dustin.flex.rest.SimpleHttpServer</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>SimpleHttpServer</servlet-name>
<url-pattern>/httpServer</url-pattern>
</servlet-mapping>

</web-app>


If we build the servlet shown above and assemble it with the web.xml file shown above into a WAR file that is deployed to a Java EE web server, we can then have clients contact the simple servlet via one of the four HTTP methods GET, POST, PUT, and DELETE (assuming the client is capable of using these different HTTP methods). In fact, we'll also see later in this blog post that even the HTTP methods TRACE, OPTIONS, and HEAD are supported by the HttpServlet. I did not override them in my servlet above because the default implementations of these methods (doTrace, doOptions, and doHead) typically work well for what we need.

For the example in this blog posting, I am deploying the assembled WAR with the servlet and web.xml file shown above to GlassFish (though any Java EE web/application server will work) using a context of restful. Coupled with the path defined in the web descriptor file and using the default port on GlassFish, my overall URL for accessing my servlet is http://localhost:8080/restful/httpServer. When I place this URL in my web browser, the results appear as shown in the figures below for Firefox and for Google Chrome.





Note that in both cases, the default method used for the browser communication with the servlet was HTTP GET. I will now begin using RESTClient to easily communicate with this servlet with alternative HTTP methods. This tool is provided as an executable JAR and is easily used, but additional instructions on using it are available here and here.

Because the browsers automatically demonstrated use of a client using HTTP GET to communicate with the server, I will begin showing RESTClient examples with GET as well. The following two screen snapshots demonstrate RESTClient showing the headers and then the body of the response. The HTTP response information is shown at the bottom of the UI.

HTTP GET Response Headers



HTTP GET Response Body




The two screen snapshots above use RESTClient to show the headers and body of the HTTP GET response. For POST, PUT, and DELETE, I will only show the bodies.


HTTP POST Response Body




HTTP PUT Response Body




HTTP DELETE Response Body




The response body for the TRACE method is shown next.

HTTP TRACE Response Body




The HTTP HEAD method works like the GET, but intentionally does not include a body. Similarly, the most interesting portion of the response for OPTIONS is also in the header. Because the HEAD's body is empty and the header looks like that for GET, I don't show it here. For OPTIONS, I show the headers rather than the bodies of those responses next. Note that the options provided by the server are shown in the "Allow" header field of this response.


HTTP OPTIONS Response Headers




As the "Allow" header field in the OPTIONS response indicates, the server supports the HTTP methods GET, HEAD, POST, PUT, DELETE, TRACE, and OPTIONS.


Conclusion

Although Java servlets are more than a decade old, they remain a powerful and highly useful technology. While they may not be as trendy as younger and more currently hip technologies, this blog posting serves as a reminder of how relatively easy it is to apply their rich features to modern-day development. Servlets have supported the major HTTP methods for many years and because of the HttpServlet's close association with HTTP, it is not surprising that the HttpServlet was ready for action when REST became a widely popular topic.

2 comments:

Vetal said...

How to run command line version to PUT xml???

@DustinMarx said...

With the end of Google Code hosting projects, rest-client is now hosted on GitHub.