REST stands for Representational State Transfer. It is an architecture style for designing networked applications and relies on stateless and mostly HTTP protocol.

REST is a lightweight alternative to mechanisms like RPC (Remote Procedure Calls) and Web Services (SOAP, WSDL, etc.)

Some of the examples of REST URLs are:

Method URI Purpose
GET /users Get list of users
GET /users/1 Get a particular user
PUT /users/1 Insert user with id 1
POST /users/1 Update user with id 1
DELETE /users/1 Delete user with id 1
OPTIONS /users List the options supported by web service

Creating Spring MVC Project

  1. Start Spring Source Tool Suite and create a Maven based project. File -> New Project -> Maven Project -> maven-archetype-webapp
  2. Enter following information:
     Group Id: spring_rest_test
     Artifact Id: rest
     Package: com.spring.rest
  3. If you don’t see the folder src/main/java, create a new folder named java under src/main. Then right click on project -> Maven -> Update project
  4. Update your pom.xml with following data:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
    
      <groupId>spring_rest_test</groupId>
      <artifactId>rest</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>Spring MVC REST Webapp</name>
      <url>http://maven.apache.org</url>
    
      <properties>
         <spring.version>4.2.0.RELEASE</spring.version>
         <jackson.version>2.5.3</jackson.version>
      </properties>
    
      <dependencies>
    
        <!-- servlet dependencies -->
    
        <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>3.1.0</version>
           <scope>provided</scope>
         </dependency>
    
         <dependency>
           <groupId>commons-collections</groupId>
           <artifactId>commons-collections</artifactId>
           <version>3.2.1</version>
         </dependency>
    
         <!-- spring dependencies -->
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
            <type>jar</type>
            <scope>compile</scope>
         </dependency>
    
         <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
         </dependency>
    
       </dependencies>
    
       <build>
          <finalName>spring_rest_test</finalName>
       </build>
    </project>
  5. Now create a new package: com.spring.rest.config. Then create following classes in it:

    WebConfig.java
    For web application settings.

    package com.spring.rest.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
       @Override
       public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
          configurer.enable();
       }
    }

    SpringMvcInitializer.java
    For initializing spring settings

    package com.spring.rest.config;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] { AppConfig.class };
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
           return null;
        }
    
        @Override
        protected String[] getServletMappings() {
           return new String[] { "/" };
        }
    }

    AppConfig.java
    For loading application configurations.

    package com.spring.rest.config;
    
    import javax.servlet.ServletContext;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    
    @EnableWebMvc
    @Configuration
    @ComponentScan({ "com.spring.rest.*" })
    @Import({ WebConfig.class })
    public class AppConfig {
    
         @Autowired
         ServletContext servletContext; 
    }

    Customer.java
    This will be a POJO ( Plain Old Java Object ) for now. We can later modify this example to talk to database as well. Create a new package named com.spring.rest.pojo and create a class Customer.java with following code:

    package com.spring.rest.pojo;
    import java.io.Serializable;
    
    public class Customer implements Serializable{
    
         private static final long serialVersionUID = -791609634721165745L;
    
         private long id;
         private String name;
         private String gender;
    
         public Customer(){
         }
         public Customer(long id, String name, String gender){
             this.id = id;
             this.name = name;
             this.gender = gender;
         }
         public long getId() {
            return id;
         }
         public String getName() {
            return name;
         }
         public String getGender() {
            return gender;
         }
         public void setId(long id) {
            this.id = id;
         }
         public void setName(String name) {
            this.name = name;
         }
         public void setGender(String gender) {
            this.gender = gender;
         }
    }

    Data.java
    This class will initialize and store list of customers. Create a new package named com.spring.rest.utility and create the class Data.java with following code:

    package com.spring.rest.utility;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.spring.rest.pojo.Customer;
    
    public class Data {
     
        public static List<Customer> customers;
     
        static{
           customers = new ArrayList<Customer>();
     
           customers.add(new Customer(1, "Sachin", "Male"));
           customers.add(new Customer(2, "Sania", "Female"));
           customers.add(new Customer(3, "Vijender", "Male"));
           customers.add(new Customer(4, "Usha", "Female"));
        }
    }


    CustomerController.java

    Now we will write our REST controller. Create a new package named com.spring.rest.controller. Create a new class named CustomerController. Add following code to it:

    package com.spring.rest.controller;
    
    import java.util.List;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.spring.rest.pojo.Customer;
    import com.spring.rest.utility.Data;
    
    @RestController
    public class CustomerController {
     
         @RequestMapping(value = "/customers", method = RequestMethod.GET)
         public ResponseEntity<List<Customer>> getCustomers(){
     
             if(Data.customers.isEmpty())
                  return new ResponseEntity<List<Customer>>(HttpStatus.NO_CONTENT);
             else
                  return new ResponseEntity<List<Customer>>(Data.customers, HttpStatus.OK); 
         }
     
         @RequestMapping(value = "/customers/{id}", method = RequestMethod.GET)
         public ResponseEntity<Customer> getCustomer(@PathVariable("id") long id){
     
              Customer existingCustomer = getExistingCustomer(id);
     
              if(null != existingCustomer)
                   return new ResponseEntity<Customer>(existingCustomer, HttpStatus.OK);
              else
                   return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND);
         }
     
         @RequestMapping(value = "/customers", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
         public ResponseEntity<Customer> createCustomer(@RequestBody Customer customer){
     
              Data.customers.add(customer);
     
              return new ResponseEntity<Customer>(HttpStatus.OK);
         }
     
         @RequestMapping(value = "/customers/{id}", method = RequestMethod.PUT)
         public ResponseEntity<Customer> updateCustomer(@PathVariable("id") long id, @RequestBody Customer customer){
     
            Customer existingCustomer = getExistingCustomer(id);
     
            if(null != existingCustomer){
     
                updateExistingCustomer(existingCustomer, customer);
     
                return new ResponseEntity<Customer>(HttpStatus.OK);
            }
            else
                return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND);
         }
    
         @RequestMapping(value = "/customers/{id}", method = RequestMethod.DELETE)
         public ResponseEntity<Customer> deleteCustomer(@PathVariable long id){
     
             Customer existingCustomer = getExistingCustomer(id);
     
             if(null != existingCustomer){
     
                  removeCustomer(id);
     
                  return new ResponseEntity<Customer>(HttpStatus.NO_CONTENT);
             }
             else
                  return new ResponseEntity<Customer>(HttpStatus.OK);
         }
    
         /************** other methods, usually put in service classe *************/
     
         private void updateExistingCustomer(Customer existingCustomer, Customer customer) {
     
             existingCustomer.setName(customer.getName());
             existingCustomer.setGender(customer.getGender());
         }
    
         private Customer getExistingCustomer(long id) {
    
            for(Customer customer : Data.customers)
                if(customer.getId()==id)
                    return customer;
     
            return null;
         }
     
         private void removeCustomer(long id) {
    
             for(int i=0; i<Data.customers.size(); i++)
                  if(Data.customers.get(i).getId()==id){
                       Data.customers.remove(i);
                       break;
                  } 
         } 
    }
  6. Now our controller is ready. Run the application on the server and execute the following URL:
    http://localhost:8080/restful/customers

Explanation of things:

ResponseEntity    :     This is a class that represents entire HTTP response. With this, we can control status code, headers, body etc.

HttpStatus             :      Enumeration of HTTP status codes.

RequestBody         :      Annotation indicating that method parameter should be bound to the body of the web request. In this example, it will bind posted data to specified object.