REST and SOAP – Web services analogy

The World Wide Web is evolving from a sea of information to a service oriented marketplaces and Web Services are a critical part of this evolution.

What is a Web service?

A web service is a method of communication between two electronic devices over the World Wide Web.

W3C defines web service as a “software system designed to support interoperable machine-to-machine interaction over a network. It has an interface described in a machine-processable format (specifically WSDL). Other systems interact with the Web service in a manner prescribed by its description using SOAP messages, typically conveyed using HTTP with an XML serialization in conjunction with other Web-related standards.” [1]

Web service diagram - Manish Chhabra

A more constrained architectural style for reliable Web applications known as Representation State Transfer (REST) was proposed by Roy Fielding. [2] In a REST-style architecture requests and responses are built around the transfer of representations of resources. A resource (e.g. Person) can be essentially any coherent and meaningful concept that may be addressed. A representation of a resource is typically a document (e.g. XML or JSON) that captures the current or intended state of a resource.

What is SOAP?

SOAP is a protocol specification for exchanging structured information in the implementation of Web Services. It uses XML for the message format. It is independent of the transport protocol (could be HTTP, FTP, TCP, UDP, or named pipes).

SOAP based services strictly define the format of messages passed back and forth. A SOAP message contains the data, the action to perform on it, the headers, and the error details in case of failure. Security is provided by WS-Security standards and is end-to-end. It supports identity through intermediaries, not just point to point (SSL).

SOAP provides a mechanism for services to describe themselves to clients (WSDL), and to advertise their existence (UDDI). SOAP also provides reliable messaging (WS-ReliableMessaging), that is a successful retry logic built in and provides end to end reliability through soap intermediaries.

What is REST?

Representational State Transfer (REST) is an architecture style for designing networked applications, that

  1. Involves clients and servers sending request and responses respectively.
  2. Request and response are built around the transfer of representations of resources.
    (e.g. request JSON representation of User)

REST recognises everything a resource (e.g. User, Lottery, etc.) and each resource implements a standard uniform interface (typically HTTP interface), resources have name and addresses (URIs), each resource has one or more representation (like JSON or XML) and resource representations move across the network usually over HTTP.

RESTful web APIs (or RESTful web service) is a web API implemented using HTTP and principles of REST. RESTful API separates user interface concerns from data storage concerns. It improves portability of interface across multiple platforms and simplifies server components by making them stateless. Each request from client contains all the state information and server does not hold client context in the session.

SOAP vs REST?

One of the major benefits of SOAP is that you have a WSDL service description. You can pretty much discover the service automatically and generate a useable client proxy from that service description (generate the service calls, the necessary data types for the methods and so forth). Note that with version 2.0, WSDL supports all HTTP verbs and can be used to document RESTful services as well, but there is a less verbose alternative in WADL (Web Application Description Language) for that purpose.

With RESTful services, message security is provided by the transport protocol (HTTPS), and is point-to-point only. It doesn’t have a standard messaging system and expects clients to deal with communication failures by retrying. SOAP has successful/retry logic built in and provides end-to-end reliability even through SOAP intermediaries.

One of the major benefits of RESTful API is that it is flexible for data representation, for example you could serialize your data in either XML or JSON format. RESTful APIs are cleaner or easier to understand because they add an element of using standardised URIs and gives importance to HTTP verb used (i.e. GET, POST, PUT and DELETE).

RESTful services are also lightweight, that is they don’t have a lot of extra xml markup. To invoke RESTful API all you need is a browser or HTTP stack and pretty much every device or machine connected to a network has that.

Finally, which ever architecture you choose make sure its easy for developers to access it, and well documented.

Tagged , , ,

Spring Data MongoDB example with Spring MVC 3.2

Here is another example web application built with Spring MVC 3.2 and Spring Data 1.2, integrating with the MongoDB document database.

STEP 1: Create new webapp project, I will use maven for this. (Note: I am on my macbook with Maven 3 and Java 6 installed.)

mvn archetype:generate \
-DgroupId=com.manishchhabra.blog \
-DartifactId=HelloSpringWithMongoDB \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false

You could create the maven project directly in your IDE as well. But I usually create it on the terminal and import it in eclipse by using the following command (Note: The following command is run within your newly created project directory, i.e. run -> cd HelloSpringWithMongoDB)

mvn eclipse:eclipse -Dwtpversion=2.0

STEP 2: Add Spring Framework 3.2 and Spring Data 1.2 dependencies to your pom.xml


		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-mongodb</artifactId>
			<version>1.2.0.RELEASE</version>
		</dependency>



STEP 3: Update your web.xml (src/main/webapp/WEB-INF/web.xml) to use Spring’s DispatcherServlet

<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	    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">

  <display-name>Spring With MongoDB Web Application</display-name>

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

</web-app>




STEP 4: Add your spring configuration to the dispatcher-servlet.xml

  • Use MongoFactoryBean to connect to the MongoDB instance.
  • Use MongoTemplate to connect and make queries to the database.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

	<context:component-scan base-package="com.manishchhabra.blog" />

	<!-- Factory bean that creates the Mongo instance -->
	<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
		<property name="host" value="localhost" />
	</bean>
	
	<!-- MongoTemplate for connecting and quering the documents in the database -->
	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
		<constructor-arg name="mongo" ref="mongo" />
		<constructor-arg name="databaseName" value="test" />
	</bean>

	<!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    
       	
   	<bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />	

</beans>




STEP 5: Create a model (using Person as an example), service and controller in the new source directory src/main/java
Model

package com.manishchhabra.blog.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class Person {

	@Id
	private String id;
	private String name;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

Service

package com.manishchhabra.blog.service;

import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;

import com.manishchhabra.blog.model.Person;

@Repository
public class PersonService {
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	public static final String COLLECTION_NAME = "person";
	
	public void addPerson(Person person) {
		if (!mongoTemplate.collectionExists(Person.class)) {
			mongoTemplate.createCollection(Person.class);
		}		
		person.setId(UUID.randomUUID().toString());
		mongoTemplate.insert(person, COLLECTION_NAME);
	}
	
	public List<Person> listPerson() {
		return mongoTemplate.findAll(Person.class, COLLECTION_NAME);
	}
	
	public void deletePerson(Person person) {
		mongoTemplate.remove(person, COLLECTION_NAME);
	}
	
	public void updatePerson(Person person) {
		mongoTemplate.insert(person, COLLECTION_NAME);		
	}
}

Controller for the CRUD operations

package com.manishchhabra.blog.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.RedirectView;

import com.manishchhabra.blog.model.Person;
import com.manishchhabra.blog.service.PersonService;
   
@Controller    
public class PersonController {  
   
	@Autowired
	private PersonService personService;
	
    @RequestMapping(value = "/person", method = RequestMethod.GET)  
	public String getPersonList(ModelMap model) {  
        model.addAttribute("personList", personService.listPerson());  
        return "output";  
    }  
    
    @RequestMapping(value = "/person/save", method = RequestMethod.POST)  
	public View createPerson(@ModelAttribute Person person, ModelMap model) {
    	if(StringUtils.hasText(person.getId())) {
    		personService.updatePerson(person);
    	} else {
    		personService.addPerson(person);
    	}
    	return new RedirectView("/HelloSpringWithMongoDB/person");  
    }
        
    @RequestMapping(value = "/person/delete", method = RequestMethod.GET)  
	public View deletePerson(@ModelAttribute Person person, ModelMap model) {  
        personService.deletePerson(person);  
        return new RedirectView("/HelloSpringWithMongoDB/person");  
    }    
}

STEP 5: Create a JSP Page in the folder WEB-INF/jsp called output.jsp (This will currently invoke create and delete).

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
	<h2>Here is a simple CRUD using Spring MVC and MongoDB.</h2>

		<form action="person/save" method="post">
			<input type="hidden" name="id">
			<label for="name">Person Name</label>
			<input type="text" id="name" name="name"/>
			<input type="submit" value="Submit"/>
		</form>

	<table border="1">
		<c:forEach var="person" items="${personList}">
			<tr>
				<td>${person.name}</td><td><input type="button" value="delete" onclick="window.location='person/delete?id=${person.id}'"/></td>
			</tr>
		</c:forEach>
	</table>	
</body>
</html>

STEP 6: That’s it! Its time to run your project. You could either run directly from eclipse or you could run “mvn package” to build a war file and deploy it to your application server. I tested this on tomcat running on port 8080 (http://localhost:8080/HelloSpringWithMongoDB/person) and I could store and delete person with provided names. Working! yeah.. Here is a picture of me playing with the app :)

Spring Data MongoDB Spring MVC 3.2 Example App

Spring Data MongoDB Spring MVC 3.2 Example App


You can view or download the full project code at https://github.com/manishchhabra/HelloSpringWithMongoDB

Cheers

Tagged , , , ,

Hello world with Spring MVC 3.2 – Spring framework tutorial

I have written hello world using Spring web app so many times that I think its about time I share it on my blog.

STEP 1: Create new webapp project, I will use maven for this. (Note: I am on my macbook with Maven 3 and Java 6 installed.)

mvn archetype:generate \
-DgroupId=com.manishchhabra.blog \
-DartifactId=HelloSpringMVC \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false

You could create the maven project directly in your IDE as well. But I usually create it on the terminal and import it in eclipse by using the following command (Note: The following command is run within your newly created project directory, i.e. run -> cd HelloSpringMVC)

mvn eclipse:eclipse -Dwtpversion=2.0

(Note: If this is the first time you are creating a maven webapp project, maven will download a lot of jar files into your local maven repository).

STEP 2: Add Spring Framework 3.2 dependencies to your pom.xml

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-orm</artifactId>
		<version>3.2.0.RELEASE</version>
	</dependency>

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>3.2.0.RELEASE</version>
	</dependency>

STEP 3: Update your web.xml (src/main/webapp/WEB-INF/web.xml) to use Spring’s DispatcherServlet

<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	    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">

  <display-name>Spring MVC Web Application</display-name>

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

</web-app>

STEP 4: Create a spring controller (HelloSpringController.java) in the new source directory src/main/java

package com.manishchhabra.blog.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
   
@Controller    
public class HelloSpringController {  
   
    @RequestMapping(value = "/hello", method = RequestMethod.GET)  
	public String printWelcome(ModelMap model) {  
        model.addAttribute("message", "Hello! This is Spring MVC Web Controller.");  
        return "output";  
    }  
}

STEP 5: Create a JSP Page in the folder WEB-INF/jsp called output.jsp

<html>
<body>
	<h2>Here is the message from HelloSpringController.</h2>
	<p>
	 	${message}
	</p>	
</body>
</html>

STEP 6: Add your spring configuration dispatcher-servlet.xml into the WEB-INF folder (includes jsp page resolver and component-scan of your base package)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
    <context:component-scan base-package="com.manishchhabra.blog"/>
       	
   	<bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />	

</beans>

STEP 6: That’s it! Its time to run your project. You could either run directly from eclipse or you could run “mvn package” to build a war file and deploy it to your application server. I tested this on tomcat running on port 8080 (http://localhost:8080/HelloSpringMVC/hello), gave me a message from my Spring Controller. Working! yeah :)

You can view or download the full project code at https://github.com/manishchhabra/HelloSpringMVC

Cheers

Tagged , , ,