Spring RESTful web services example with Maven

In this article we will see how to create a "Spring RESTful web services with Maven" using Spring 5 and Java 8. We will also look into required maven dependencies and configurations.

Please make sure you have Java8+ and Maven 3+ already installed on your machine, spring 5 requires Java8+. In order to chek if Java8 is installed please follow the instructions below:

$ java -version

java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)


To ensure Maven 3+ is already installed, please follow the instructions below:

mvn --version

Apache Maven 3.5.2
Maven home: /usr/share/maven
Java version: 1.8.0_181, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_IN, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-43-generic", arch: "amd64", family: "unix"


Step 1: Create a Java web project with maven

In order to create a Java web project with maven, follow the instruction given below:

mvn archetype:generate -DgroupId=com.tb.sample -DartifactId=SampleSpringRest -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

To make this project compitable with eclipse, dive into the created project directory and run following commands:

mvn eclipse:eclipse -Dwtpversion=2.0

Import this project into eclipse, using eclipse import wizard: File > Import > General > Existing Projects into Workspace

Step 2: Add required maven dependencies in pom.xml

SampleSpringRest/pom.xml

<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>com.tb.sample</groupId>
	<artifactId>SampleSpringRest</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>SampleSpringRest Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<properties>
		<spring.version>5.1.2.RELEASE</spring.version>
		<jdk.version>1.8</jdk.version>
		<jackson.databind-version>2.9.5</jackson.databind-version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.databind-version}</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>SampleSpringProject</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>${jdk.version}</source>
					<target>${jdk.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Step 3: Clean install Maven

Go to project directory and clean install maven to download dependencies and compile the project, using following command:

mvn clean install
mvn eclipse:eclipse -Dwtpversion=2.0


Step 4: Changes in web.xml

We will now add "DispatcherServlet" entry in web.xml, this will tell the container that all upcoming requests will be handled by spring with the help of configurations written in "mvc-dispatcher-servlet.xml".

SampleSpringRest/src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">

	<display-name>Maven Project</display-name>
	<!-- Spring MVC -->
	<servlet>
		<servlet-name>mvc-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>mvc-dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

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

Step 5: Add spring configuration

In mvc-dispatcher-servlet.xml, we have added a "component-scan base-package" with value "com.techburps.*", this indicates that in order to resolve annotations like "@RestController", spring will look into child packages of "com.techburps" only.

SampleSpringRest/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml

<?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:util="http://www.springframework.org/schema/util"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
  http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

	<context:component-scan
		base-package="com.techburps.*" />
	<mvc:annotation-driven />
</beans>

Step 6: Add a Resource bean

Lets create a resource class, Student.java; we will write our RESTful webservices around Student resource for adding, updation, get, list and delete:

package com.techburps.model;
import java.io.Serializable;

public class Student implements Serializable{

	private static final long serialVersionUID = 1L;
	private int id;
	private String name;
	private int age;

	public Student() {
	}

	public Student(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	// Getter & Setters

}

Step 7: Add a Rest Controller

@Controller, Indicates that an annotated class is a web controller, to be autodetected through classpath scanning. It is genrally used in combination with handler methods annotated by @RequestMapping.

@RequestMapping, maps HTTP requests to handler methods of MVC controllers, in this case a request for "/home" will be handled by "home()" method.

@RestController is a specialized version of the @Controller. It includes the @Controller and @ResponseBody annotations and as a result, simplifies the controller implementation.

@ResponseBody is used to annotate a method, it tries to convert method's return value and write it to the http response automatically.

@RequestBody is used to annotate a method, it tries to convert the content of the incoming request body to the parameter object on the fly.

We have routes for each operations (@GetMapping, @PostMapping, @PutMapping and @DeleteMapping, corresponding to HTTP GET, POST, PUT, and DELETE calls).

SampleSpringRest/src/main/java/com/techburps/controller/StudentController.java

package com.techburps.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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.techburps.model.Student;

@RestController
@RequestMapping("student")
public class StudentController {

	/* Adding a resource */
	@PostMapping(value="/")
	public Student add(@RequestBody Student student) {
		// Code for adding goes here
		// returning added resource
		return student;
	}

	/* Updating a resource */
	@PutMapping("/")
	public Student update(@RequestBody Student student) {
		// Code for updation goes here
		// returning updated resource
		return student;
	}

	/* Getting list of all resources */
	@GetMapping("/")
	public List<Student> list() {

		// Dummy students list
		List<Student> students = new ArrayList<>();
		students.add(new Student(1, "techburps-1", 20));
		students.add(new Student(2, "techburps-2", 22));
		students.add(new Student(3, "techburps-3", 24));

		return students;
	}

	/* Getting a single resource by id */
	@GetMapping("/{id}")
	public Student get(@PathVariable int id) {

		// Dummy student object
		Student student = new Student(1, "techburps", 20);

		return student;
	}

	/* Deleting a resource by id */
	@DeleteMapping("/{id}")
	public int delete(@PathVariable int id) {
		// Code for deletion goes here
		return id;
	}

}

Step 8: Test APIs

Now we are done with adding all required files and configurations, the project structure should look like this:

Now lets run the project, and test our APIs:

1) Add a resource - POST

http://localhost:8080/SampleSpringRest/student/

Content-Type: application/json
Request Body: {"id": 1, "name": "techburps-1", "age": 20}

2) Update a resource - PUT

http://localhost:8080/SampleSpringRest/student/

Content-Type: application/json
Request Body: {"id": 5, "name": "techburps-5", "age": 20}

3) Getting list of resources - GET

http://localhost:8080/SampleSpringRest/student/

4) Getting a resource by its id - GET

http://localhost:8080/SampleSpringRest/student/1

5) Deleting a resource by its id - DELETE

http://localhost:8080/SampleSpringRest/student/1