Complete tutorial of creating RESTful API with Spring.

Configuration
Java Compilation:
Java Runtime:
Web Server:
Maven:
Java Compilation:
Java Runtime:
Web Server:
Gradle:
JDK 17.0.2
JRE OpenJDK 17.0.2
Tomcat 10.1.16
Maven 3.9.6
JDK 17.0.2
JRE OpenJDK 17.0.2
Tomcat 10.1.16
Gradle 8.6
Create the following folder structure:
folder structure of Create first RESTful API with Spring
pom.xml: (if using Gradle, replace pom.xml with build.gradle)
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.maxjava</groupId> <artifactId>FirstSpringRESTAPI</artifactId> <version>1.0</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.1.6</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.4</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> </plugins> </build> </project>
plugins { id 'java' id 'war' } java { sourceCompatibility = 17 targetCompatibility = 17 } group 'net.maxjava' version '1.0' repositories { mavenCentral() } dependencies { implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.4' implementation group: 'org.springframework', name: 'spring-webmvc', version: '6.1.6' compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.30' annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.30' }
Some notes about pom.xml:
  • spring-webmvc for necessary Spring REST controllers and its dependencies
  • jackson-databind is for the java object serialization and deserialization
  • lombok to remove boilerplate code like get and set
  • maven-compiler-plugin is for compiling the code using source version 17 and target version 17
  • A war artifact will be created for deployment to servlet containers
Some notes about build.gradle:
  • spring-webmvc for necessary Spring REST controllers and its dependencies
  • jackson-databind is for the java object serialization and deserialization
  • lombok to remove boilerplate code like get and set
  • targetCompatibility is used to configure compilation with source version 17 and target version 17
  • A war artifact will be created for deployment to servlet containers
web.xml:
<web-app> <display-name>First Spring REST API</display-name> <servlet> <servlet-name>FirstSpringRESTAPI</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/myApplicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>FirstSpringRESTAPI</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Some notes about web.xml:
  • org.springframework.web.servlet.DispatcherServlet is the servlet class for Spring
  • /WEB-INF/myApplicationContext.xml is the location of the Spring context configuration file
myApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="controller"/> <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven> </beans>
Some notes about myApplicationContext.xml:
  • <context:component-scan base-package="controller"/> is for Spring to look for classes in specific packages to create beans
  • <mvc:message-converters> is to specify library for json serialization and deserialization
MyController.java:
package controller; import model.Square; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/myapp") public class MyController { @GetMapping("/square") public Square getSquare(@RequestParam("side") int side, @RequestParam("color") String color) { Square square = new Square(); square.setArea(side * side); square.setColor(color); return square; } @PostMapping("/square") public String postSquare(@RequestBody Square square) { return "Got square, which the side is " + Math.sqrt(square.getArea()); } }
Some notes about MyController.java:
  • Specifying @RestController will make this a controller to handle web request. Using @RestController instead of @Controller to perform serialization automatically, without the need of using @ResponseBody
  • @RequestMapping("/myapp") + @GetMapping("/square") will make the getSquare function map to the path in the URL to GET /myapp/square
  • @RequestParam will map to the query param side and color
  • @RequestMapping("/myapp") + @PostMapping("/square") will make the postSquare function map to the path in the URL to POST /myapp/square
  • @RequestBody is to perform de-serialization into the Java object
Square.java:
package model; import lombok.Data; @Data public class Square { private String color; private int area; }
Some notes about Square.java:
  • This is the object used in the request or response body on the Controller APIs
  • Use Lombok @Data for get and set
Sample output(assume the war file is deployed to <CONTEXT_PATH>):
  • GET:
    curl --request GET '<CONTEXT_PATH>/myapp/square?side=12&color=blue'
    Response:
    { "color": "blue", "area": 144 }
  • POST:
    curl --request POST '<CONTEXT_PATH>/myapp/square' --header 'Content-Type:application/json' --data ' { "color": "blue", "area": 144 }'
    Response:
    Got square, which the side is 12.0