In his dissertation, Roy Fielding articulated REST as an underlying concept for today's Web architecture (see Resources at the end of this article for a link to Fielding's dissertation). He laid out the following criteria for REST:
- A set of constraints to model the modern Web architecture
- REST principles were applied to HTTP and URI specs
- Visible in the evolution of HTTP
REST is not a protocol; rather it's an architectural style — an important distinction.
As for Web services, the official W3C take on a Web service definition is as follows:
"A Web service is a software system identified by a URI, whose public interfaces and bindings are defined and described using XML. Its definition can be discovered by other software systems. These systems may then interact with the Web service in a manner prescribed by its definition, using XML based messages conveyed by internet protocols." (See Resources for a link to the source of this excerpt.)
Common sense tells us that Web services are meant for machine-to-machine communication as opposed to machine-to-user communication. A RESTful Web service is a Web service built using the REST architectural style, and the next section demonstrates how to build a RESTful Web service using an example. To grasp this, it's important that you understand Ajax. (If you're new to Ajax, refer to Resources for links to helpful information.)
Creating a RESTful Web service
To create a RESTful Web service, first you need to identify all the resources you want to expose as Web services. Some examples of resources include employee list, employee detail, purchase order, and so on. In REST, every resource is identified by a unique Uniform Resource Identifier (URI). You need to decide on a unique URI for every resource. For example, an employee list can be identified by a URI like this: http://www.employee-details.com/employees-list. An employee detail can be represented by a URI like this: http://www.employee-details.com/employees/01234.
Use the HTTP operations GET, PUT, POST, and DELETE to retrieve and modify your resources. Provide hyperlinks in your resource representation to allow for more — and related — information. Specify a format for requesting and responding to data for resources, which requires PUT and POST operations.
The diagram in Figure 1 shows the interaction with a RESTful Web service.
Figure 1. Interaction with a RESTful Web service
Implementing a RESTful Web service
You can implement a RESTful Web service using an HTTP servlet. This article illustrates the implementation using a dummy service that provides details about employees of a company. An employee list resource is represented using a logical URI, http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list. When this service is invoked with HTTP GET, it returns a list of employees as shown in Listing 1.
Listing 1. Employee list invoked with HTTP GET
<?xml version='1.0' encoding='UTF-8'?>
<p:Employees xmlns:p='http://www.employee-details.com'>
<Employee id='00345' href='/employees/00345'/>
<Employee id='00346' href='/employees/00346'/>
<Employee id='00347' href='/employees/00347'/>
<Employee id='00348' href='/employees/00348'/>
</p:Employees>
|
Similarly, an employee detail can be represented by a logical URI, such as http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee/0124. When this service is invoked with HTTP GET, it returns an employee detail as shown in Listing 2.
Listing 2. Employee detail invoked with HTTP GET
<?xml version='1.0' encoding='UTF-8'?>
< EmpDetail xmlns:p='http://www.employee-details.com'>
<<Emp-ID>00345</Emp-ID>
<Name>David Henry</Name>
<Department>Finance</ Department >
</p:EmpDetail>
|
Listing 3 shows the servlet code. Everything is hardcoded here but can easily be extended to interact with a database to become a real-time RESTful service.
Listing 3. Servlet code
public class RESTDemoServlet extends HttpServlet implements Servlet {
/* (non-Java-doc)
* @see javax.servlet.http.HttpServlet#HttpServlet()
*/
Map map =new HashMap();
/* (non-Javadoc)
* @see javax.servlet.GenericServlet#init()
*/
public void init() throws ServletException {
// TODO Auto-generated method stub
super.init();
Employee emp0 =new Employee("David","Finance");
Employee emp1 =new Employee("Smith","HealthCare");
Employee emp2 =new Employee("Adam","Information technology");
Employee emp3 =new Employee("Stephan","Life Sciences");
map.put("00345",emp0);
map.put("00346",emp1);
map.put("00347",emp2);
map.put("00348",emp3);
}
/* (non-Java-doc)
* @see javax.servlet.http.HttpServlet#doGet
(HttpServletRequest arg0, HttpServletResponse arg1)
*/
protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
// TODO Auto-generated method stub
arg1.setContentType("text/xml");
PrintWriter out=arg1.getWriter();
System.out.println(map);
if(arg0.getPathInfo()!= null){
String EmpId=arg0.getPathInfo().substring(1,arg0.getPathInfo().length());
System.out.println(EmpId);
out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
out.write("<p:EmpDetail xmlns:p='http://www.employee-details.com' >"+"\n");
out.write("<Emp-ID>"+EmpId+" </Emp-ID >"+"\n");
out.write("<Name>"+((Employee)map.get(EmpId)).name+" </Name >"+"\n");
out.write("<Department >"+((Employee)map.get(EmpId)).dept+" </Department >"+"\n");
out.write("</p:EmpDetail >"+"\n");
out.flush();
}else{
out.write("<?xml version='1.0' encoding='UTF-8'? >"+"\n");
out.write("<p:Employees xmlns:p='http://www.employee-details.com' >"+"\n");
out.write("<Employee id='00345' href='http://localhost:9080/
AJAX_REST_Demo/RESTDemoServlet/employees/00345'/ >"+"\n");
out.write("<Employee id='00346' href='http://localhost:9080/
AJAX_REST_Demo/RESTDemoServlet/employees/00346'/ >"+"\n");
out.write("<Employee id='00347' href='http://localhost:9080/
AJAX_REST_Demo/RESTDemoServlet/employees/00347'/ >"+"\n");
out.write("<Employee id='00348' href='http://localhost:9080/
AJAX_REST_Demo/RESTDemoServlet/employees/00348'/ >"+"\n");
out.write("</p:Employees >");
out.flush();
}
}
/* (non-Java-doc)
* @see javax.servlet.http.HttpServlet#doPost
(HttpServletRequest arg0, HttpServletResponse arg1)
*/
protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
|
In next section, learn how to write an Ajax client for this RESTful Web service.
Writing an Ajax client for the RESTful Web service
As indicated earlier, Ajax stands for Asynchronous JavaScript + XML. This is also
called the XML HTTP technique. In Ajax, core techniques are centered around asynchronous
communication to the server without a page refresh. An XMLHTTPRequest object allows for asynchronous GETs, POSTs, PUTs, nd
DELETEs to the server. This doesn't show anything to the user; in other words, no status
messages are shown. You can specify a handler method for state changes, and the handler is notified when the request is:
- Initialized
- Started
- In the process of being returned
- Completely finished
Listing 4 shows the code for an Ajax-based HTML page, which acts as the client to the above RESTful Web service:
Listing 4. Code for an Ajax-based HTML page
<SCRIPT language="javascript" type="text/javascript" >
var req=null;
//This function initializes XHR
function initXHR() {
if (navigator.appName.indexOf("Microsoft") > -1 ) {
try{
req=new ActiveXObject("Microsoft.XMLHTTP");
}catch(e1){
alert("failed to create XHR in IE");
}
}else{
try{
req=new XMLHttpRequest();
}catch(error){
alert("failed to create XHR in FireFox");
}
}
}
//get an employee detail
function getEmpDetails(Empurl){
initXHR();
req.open("GET",Empurl, true);
req.onreadystatechange=handleEmpDetailResponse;
req.send(null);
}
//get employee list
function getEmployeeList(listurl){
initXHR();
req.open("GET", listurl, true);
req.onreadystatechange=handleEmpListResponse;
req.send(null);
}
function handleEmpDetailResponse(){
//if Response is complete
if(req.readyState==4){
//response is OK
if(req.status==200){
var str="";
var response=req.responseXML;
var root=response.documentElement;
for(i=0;i <root.childNodes.length;i++){
if(root.childNodes[i].nodeType != 1) continue;
var name=root.childNodes[i].nodeName;
var value=root.childNodes[i].firstChild.nodeValue;
str=str+name+"--- >"+value+" <br >";
}
document.getElementById("emp-div").style.display="";
document.getElementById("emp-detail-div").innerHTML=str;
}else{
document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000;
font-size:12pt; text-decoration:none;' <Invalid URL or PartId </SPAN >";
}
req.abort();
}
}
function handleEmpListResponse(){
//if Response is complete
if(req.readyState==4){
//response is OK
if(req.status==200){
var pstr="";
var response=req.responseXML;
var root=response.documentElement;
for(i=0;i <root.childNodes.length;i++){
if(root.childNodes[i].nodeType != 1) continue;
var id=root.childNodes[i].getAttribute("id");
var href=root.childNodes[i].getAttribute("href");
pstr=pstr+"EmpId"+"--- >"+id+" <input type='button' value='
GetEmpDetails' onclick="+'"'+"getEmpDetails('"+href+"')"+'"'+">"+" <br >";
}
document.getElementById("emp-list-div").style.display="";
document.getElementById("emp-list").innerHTML=pstr;
}else{
document.getElementById("messageDiv").innerHTML=" <SPAN style='color:#FF0000;
font-size:12pt; text-decoration:none;' >Invalid Employee ID. </SPAN >";
}
}
}
</SCRIPT >
<center >
<input type="button" value="getEmployee-List" onclick="getEmployeeList
'http://localhost:9080/AJAX_REST_Demo/RESTDemoServlet/employee-list')" > <br > <br >
<div id="messageDiv" > </div >
<div id="emp-list-div" style='color:#FF0000; font-size:12pt; text-decoration:none;
display:none;' >Employee List : </div > <br >
<div id="emp-list" > </div > <br > <br >
<div id="emp-div" style='color:#FF0000; font-size:12pt; text-decoration:none;
display:none;' >Selected Employee Detail : </div > <br >
<div id="emp-detail-div" > </div >
</center >
|
In Listing 4, when a user clicks the
getEmployee-List button, an XML HTTP request is sent to the server. A handler
function, handleEmpListResponse, is specified to the XML HTTP request for readyState changes. When the server completes the response (readyState = 4) and the response is OK, you parse the XML and append
it into the Document Object Model (DOM) of the page to show the employee list.
Similarly, when the user clicks the GetEmpDetails button, a handler function,
handleEmpDetailResponse, handles the XML response from the server and modifies the page DOM to show the details of a particular employee.
In this article, you learned how to write a RESTful Web service using a servlet and an Ajax-based client. Hopefully you discovered that RESTful Web services can be easy to understand and implement. Be sure to check out the useful links in the Resources section below.
Learn
- Roy Fielding's dissertation, "Architectural Styles and the Design of Network-based Software Architectures," is the seminal work on the topic.
-
Web services Architecture from the W3 is a great overview of what constitutes a Web service.
- Check out the "Mastering
Ajax" series from developerWorks for a thorough overview of the topic.
- Read "Building Web services the REST
way" for a good background on the topics covered in this article.
- Check out another great article on
RESTful Web services.
- The SOA and Web services zone on IBM® developerWorks hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services
applications.
- The IBM SOA Web site offers an overview of SOA and how IBM can help you get there.
- Stay current with developerWorks technical events and webcasts.
- Browse for books on these and other technical topics at the
Safari bookstore.
- Check out a quick Web services on demand demo.
Get products and technologies
- Innovate your next development project with
IBM trial software, available for download or on DVD.
Discuss
- Participate in the discussion forum.
- Get involved in the developerWorks community by participating in developerWorks blogs.



