Background
In a recent project I worked on, RESTful web service displaced other design models such as SOAP and XML-RPC because of its simpler style. Users can operate resources by making AJAX a call in browser. And the response is in JSON, a popular response format for REST. AJAX is popular among users and REST makes things simpler. Together, AJAX and REST web application deliver a better experience.
So, what is a RESTful web service? And how can you create an AJAX and REST web application? Let’s talk about that.
RESTful web service
A RESTful web service is a web service implemented using HTTP and the principles of REST. It is a collection of resources, with these defined aspects:
- Well defined URI for the web service, such as http://app/resources/{id}
- Well documented response. The response is often JSON, XML, but can be any other valid Internet media type. JSON is supported by many modern programming languages.
- GET request should never cause a state change. Anything that changes the server state should be a POST request. Many browsers do not support PUT and DELETE method.
AJAX and REST
AJAX creates a good user experience, and updates resources view without a full page refresh. Why not combine AJAX with REST? It’s simple and scalable. RESTful web service and AJAX REST client follow REST architectural principles.
Many applications prove that this architecture is successful, such as:
- Flickr (http://www.flickr.com/services/api/)
- Gmail (https://mail.google.com/)
- Weibo (http://open.weibo.com/wiki/)
Building an Example Application
The example in this section walks through setting up the Spring environment, using jQuery for AJAX interactions and creating a “Hello world” application that can be integrated into Tomcat.
1. Configuration
/WEB-INF/web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>service</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>service</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
/WEB-INF/service-servlet.xml
<context:component-scan base-package=“com.app.controller” />
<bean class=“org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter” />
/src/app-context.xml
<beans:beans xmlns=“http://www.springframework.org/schema/mvc”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xmlns:beans=“http://www.springframework.org/schema/beans”
xmlns:context=“http://www.springframework.org/schema/context”
xsi:schemaLocation=“
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd”>
<annotation-driven />
<context:component-scan base-package=“com.app” />
</beans:beans>
2. Server code
ContactController.java
@Controller
@RequestMapping(“/contact”)
public class ContactController {
private ContactService contactService;
@Autowired
public void initService(ContactService contactService) {
this.contactService = contactService;
}
@RequestMapping(method = RequestMethod.GET, value = “/{name}”)
public @ResponseBody
Contact getContact(@PathVariable String name) {
return contactService.getContactByName(name);
}
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody
Contact saveContact(Contact contact) {
contactService.saveContact(contact);
return contact;
}
@RequestMapping(method = RequestMethod.GET)
public @ResponseBody
List<Contact> list(Contact contact) {
return contactService.list();
}
}
ContactServiceImpl.java
@Service
public class ContactServiceImpl implements ContactService {
private Map<String, Contact> contacts = new HashMap<String, Contact>();
public Contact getContactByName(String name) {
return contacts.get(name);
}
public void saveContact(Contact contact) {
if (contact.getName()==null || “”.equals(contact.getName().trim())) {
return;
}
contacts.put(contact.getName(), contact);
}
public void removeContactByName(String name) {
contacts.remove(name);
}
public List<Contact> list() {
return new ArrayList<Contact>(contacts.values());
}
}
3. Client code
Index.html
<!DOCTYPE html>
<html>
<head>
<style>
</style>
<script src=“script/jquery.js”></script>
<script>
$(function() {
$(‘#addBtn’).click(function() {
$.ajax({
type: ‘POST’,
url: ‘service/contact’,
data: {
name: $(‘#name’).val(),
email: $(‘#email’).val()
},
success: function() {
list();
}
})
});
list();
})
function list() {
$.getJSON(‘service/contact’, function(contacts) {
if(!contacts || !contacts.length) return;
$(‘#contacts’).empty();
for(i=0;i<contacts.length;i++) {
$(‘#contacts’).append(‘<li><a target=”_blank” href=”service/contact/’+contacts[i].name+'”>’+contacts[i].name+'</a>, ‘+contacts[i].email+'</li>’);
}
})
}
</script>
</head>
<body>
<div>
<fieldset>
<legend>Contacts</legend>
<ul id=“contacts”></ul>
</fieldset>
</div>
<div>
<table>
<tr>
<td>Name:</td>
<td>
<input type=“text” id=“name” />
</td>
</tr>
<tr>
<td>Email:</td>
<td>
<input type=“text” id=“email” />
</td>
</tr>
<tr>
<td></td>
<td>
<input type=“button” id=“addBtn” value=“Add Contact” />
</td>
</tr>
</table>
</div>
</body>
</html>
Resources
RESTful Web Services (Leonard Richardson and Sam Ruby, 2007)
AJAX and REST (http://www.ibm.com/developerworks/web/library/wa-ajaxarch/?S_TACT=105AGX52&S_CMP=cn-a-web)
Learn REST: A Tutorial (http://rest.elkstein.org/)