How to build REST application using JaveEE, SpringMVC and SpringBoot?

In today’s topic, we are going to discuss on building REST web application using 3 different frameworks: J2EE, SpringMVC and SpringBoot.

Here is a bit of introduction. So what is REST?

Representation State Transfer or simply REST, is just a way we build web services using HTTP protocol. Any web services that comform to REST, allows other services to interact with one another.

REST uses HTTP methods commonly such as GET, POST, PUT and DELETE. Of course there are more than just 4 methods, but for simplicity we are going to focus just the aforementioned ones.

Here is a brief explanation of the HTTP methods:

  • GET – To retrieve data from server
  • POST – To send data to server
  • PUT – To replace data
  • DELETE – To remove data

Here is an example. We have our web application that manages a list of users. A user has an id, a name and an email.

In the browser, we send a request via url.

GET Method – Retrieve a list of users information

The json data returned can be consumed by other application (be it another web app or mobile app)

GET Method – Retrieve one user information

POST Method – Add a new user to application

We send a GET request to confirm the addition of new user

PUT Method – Update user information

Thor decides to use godofthunder instead

DELETE Method – Remove a particular user

What is Java EE?

Java Enterprise Edition (formerly known as J2EE) is a set of specifications that extends Java SE that supports enterprise features.

You can read more about the latest Java EE 8 specifications and their components here:

👉https://www.oracle.com/technetwork/java/javaee/tech/index.html

What is Spring MVC?

To understand Spring MVC, we need to understand what is Spring. It is a framework built on top of Java platform that provides support for building application. It consists of many modules which you can read in details here 👉https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch01s02.html

Spring MVC is one of the web modules that allows you to apply model-view-controller design pattern to your application.

Spring MVC uses the DispatcherServlet to act as front controller. All incoming requests will be intercepted by DispatcherServlet, and then forwarded to the appropriate controller. The controller returns an object of ModelAndView. The DispatcherServlet, then checks the InternalResourceViewResolver to get the correct view.

What is Spring Boot?

Spring Boot is not another framework. It allows you to easily create a Spring-based application with very little configuration.

Getting Started!

Source code available:

RestApplicationWithJavaEE

In Java EE, there is specification JSR 370: Java API for Restful Web Services (JAX-RS) that denotes the set of interfaces and annotations needed to build rest services. Take note that JAX-RS is a specification and not implementation. The commonly implementation of JAX-RS includes RESTEasy and Jersey. We will go with Jersey.

Adding Jersey dependency in pom.xml and other supporting dependencies

<dependency>
	<groupId>org.glassfish.jersey.bundles</groupId>
	<artifactId>jaxrs-ri</artifactId>
	<version>2.27</version>
</dependency>
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>servlet-api</artifactId>
	<version>2.5</version>
</dependency>
<dependency>
	<groupId>javax.xml.bind</groupId>
	<artifactId>jaxb-api</artifactId>
	<version>2.2.11</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-core</artifactId>
	<version>2.2.11</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-impl</artifactId>
	<version>2.2.11</version>
</dependency>
<dependency>
	<groupId>javax.activation</groupId>
	<artifactId>activation</artifactId>
	<version>1.1.1</version>
</dependency>

Note: The javax.servlet.servlet-api is needed for handling http request and construct response.

Define Jersey Servlet Dispatcher

Next we register Jersey as Servlet Dispatcher to handle REST requests.

<servlet>
	<servlet-name>Jersey Rest Application</servlet-name>
	<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
	<init-param>
		<param-name>jersey.config.server.provider.packages</param-name>
		<param-value>com.davidcheah.controller</param-value>
	</init-param>
</servlet>

<servlet-mapping>
	<servlet-name>Jersey Rest Application</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

The parameter name jersey.config.server.provider.packages defines to Jersey where to look for the Rest services class, which is our controller class.

Add Model

Our POJO for user model class.

package com.davidcheah.model;

public class User {
	public User(int id, String name, String email) {
		super();
		this.id = id;
		this.name = name;
		this.email = email;
	}

	public User() {
		super();
	}

	private int id;
	private String name;
	private String email;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", email=" + email + "]";
	}
	
}

Add Service

This UserService class does a few things:

  • Populates a list of users using static block (Anything in the static block will be executed when the class is being loaded)
  • Provides CRUD (Create, Read, Update and Delete) functions for user
package com.davidcheah.services;

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

import com.davidcheah.model.User;

public class UserService {
	private static List<User> users = new ArrayList<User>();

	private static int usersCount = 0;
	static {
		users.add(new User(++usersCount, "Tony Stark", "ironman@avengers.inc"));
		users.add(new User(++usersCount, "Steve Rogers", "captain@avengers.inc"));
		users.add(new User(++usersCount, "Bruce Banner", "hulk@avengers.inc"));
	}

	public List<User> getAllUsers() {
		return users;
	}

	public User getUser(int id) {
		for (User user : users) {
			if (user.getId() == id) {
				return user;
			}
		}
		return null;
	}

	public User add(User user) {
		user.setId(++usersCount);
		users.add(user);
		return user;
	}

	public User delete(int id) {
		Iterator<User> iterator = users.iterator();
		while (iterator.hasNext()) {
			User user = iterator.next();
			if (user.getId() == id) {
				iterator.remove();
				return user;
			}
		}
		return null;
	}

	public User update(int id, User updatedUser) {
		for (User user : users) {
			if (user.getId() == id) {
				user.setName(updatedUser.getName());
				user.setEmail(updatedUser.getEmail());
				return user;
			}
		}
		return null;
	}
}

Add (REST) Controller

This class basically handles all the REST requests and contructs responds.

package com.davidcheah.controller;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.davidcheah.model.User;
import com.davidcheah.services.UserService;

@Path("/service")
public class UserController {

	private UserService service = new UserService();

	// http://localhost:8080/jaxrsdemo/service/users
	@GET
	@Path("/users")
	public List<User> getUsers() {
		List<User> users = service.getAllUsers();
		if (users.size() > 0)
			return users;
		throw new WebApplicationException(Response.Status.NOT_FOUND);
	}

	// http://localhost:8080/jaxrsdemo/service/users/1
	@GET
	@Path("/users/{id}")
	public User getUser(@PathParam("id") int id) {
		User user = service.getUser(id);
		if (user == null) {
			throw new WebApplicationException(Response.Status.NOT_FOUND);
		}
		return user;
	}

	// http://localhost:8080/jaxrsdemo/service/users
	@POST
	@Path("/users")
	@Consumes(MediaType.APPLICATION_JSON) // HTTP Error 415 if not JSON
	@Produces(MediaType.APPLICATION_JSON) // HTTP Error 406 if not JSON
	public Response addUser(User user) {
		User newUser = service.add(user);
		if (newUser == null) {
			throw new WebApplicationException(Response.Status.NOT_IMPLEMENTED);
		}
		String message = "User id " + newUser.getId() + " created.";
		return Response
			      .status(Response.Status.CREATED)
			      .entity(message)
			      .build();
	}

	// http://localhost:8080/jaxrsdemo/service/users/1
	@DELETE
	@Path("/users/{id}")
	public Response deleteUser(@PathParam("id") int id) {
		User removedUser = service.delete(id);
		if (removedUser == null) {
			throw new WebApplicationException(Response.Status.NOT_FOUND);
		}
		String message = "User id " + removedUser.getId() + " removed.";
		return Response
			      .status(Response.Status.OK)
			      .entity(message)
			      .build();
	}
	
	// http://localhost:8080/jaxrsdemo/service/users/1
	@PUT
	@Path("/users/{id}")
	@Consumes(MediaType.APPLICATION_JSON) // HTTP Error 415 if not JSON
	@Produces(MediaType.APPLICATION_JSON) // HTTP Error 406 if not JSON
	public Response updateUser(@PathParam("id") int id, User user) {
		System.out.println("update received");
		User updateUser = service.update(id, user);
		if (updateUser == null) {
			throw new WebApplicationException(Response.Status.NOT_IMPLEMENTED);
		}
		String message = "User id " + updateUser.getId() + " updated.";
		return Response
			      .status(Response.Status.CREATED)
			      .entity(message)
			      .build();
	}
}

Here the meaning of each annotations used:

  • Path – links the url-pattern to a class or method
  • GET, POST, DELETE, PUT – denotes method handles HTTP request
  • PathParam(“name”) – retrieves the variable from url
  • Consumes – Restricts the media type the method can accept. For example if the media type is not JSON, then http error code 415 will be thrown.
  • Produces – Restricts the media type the method produces.

Rest Application with Spring MVC

Adding dependencies to pom.xml

  • javaee-web-api for building class to handle http request and response
  • spring-webmvc for dispatcher servlet activation
  • jackson-databind for handling json data
<dependency>
	<groupId>javax</groupId>
	<artifactId>javaee-web-api</artifactId>
	<version>6.0</version>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>4.2.2.RELEASE</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.9.9</version>
</dependency>

Configure web.xml to use DispatcherServlet

<servlet>
	<servlet-name>dispatcher</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/springmvcdemo-servlet.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

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

Define bean in xml file

In this xml file we define,

  • Place for our component scanning – basically so that we can inject our class directly in anywhere of the code.
  • ViewResolver – DispatcherServlet gets the right view based on controller methods output.
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- Provide support for component scanning -->  
	<context:component-scan
		base-package="com.davidcheah" />

	<!--Provide support for conversion, formatting and validation -->  
	<mvc:annotation-driven />

	<!--Provide support for view resolver -->  
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/views/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

</beans>

Add Model

No change in User.java

Add Service

package com.davidcheah.services;

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

import org.springframework.stereotype.Service;

import com.davidcheah.model.User;

@Service
public class UserService {

	private static List<User> users = new ArrayList<User>();

	private static int usersCount = 0;
	static {
		users.add(new User(++usersCount, "Tony Stark", "ironman@avengers.inc"));
		users.add(new User(++usersCount, "Steve Rogers", "captain@avengers.inc"));
		users.add(new User(++usersCount, "Bruce Banner", "hulk@avengers.inc"));
	}

	public List<User> getAllUsers() {
		return users;
	}

	public User getUser(int id) {
		for (User user : users) {
			if (user.getId() == id) {
				return user;
			}
		}
		return null;
	}

	public User add(User user) {
		user.setId(++usersCount);
		users.add(user);
		return user;
	}

	public User delete(int id) {
		Iterator<User> iterator = users.iterator();
		while (iterator.hasNext()) {
			User user = iterator.next();
			if (user.getId() == id) {
				iterator.remove();
				return user;
			}
		}
		return null;
	}

	public User update(int id, User updatedUser) {
		User foundUser = getUser(id);
		if (foundUser == null || updatedUser == null) {
			return null;
		}
		foundUser.setEmail(updatedUser.getEmail());
		foundUser.setName(updatedUser.getName());
		return foundUser;
	}

}

The only difference is the annotation @Service. This enables us to directly inject UserService and letting Spring DI module to help us initialize it.

Add REST Controller

package com.davidcheah.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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.davidcheah.model.User;
import com.davidcheah.services.UserService;

@RestController
public class UserController {
	@Autowired
	private UserService service;

	// http://localhost:8080/users
	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public ResponseEntity<List<User>> getAllUsers() {
		List<User> foundUsers = service.getAllUsers();
		if (foundUsers.size() > 0) {
			return ResponseEntity.ok(foundUsers);
		}
		return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
	}

	// http://localhost:8080/users/1
	@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
	public ResponseEntity<User> getUser(@PathVariable int id) {
		User foundUser = service.getUser(id);
		if (foundUser != null) {
			return ResponseEntity.ok(foundUser);
		}
		return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
	}

	// http://localhost:8080/users
	@RequestMapping(value = "/users", method = RequestMethod.POST)
	public ResponseEntity<String> createUser(@RequestBody User user) {
		User newUser = service.add(user);
		if (newUser != null) {
			return ResponseEntity.ok().body("Added user id: " + newUser.getId());
		} return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
	}

	// http://localhost:8080/users/1
	@RequestMapping(value = "/users/{id}", method = RequestMethod.PUT)
	public ResponseEntity<String> updateUser(@PathVariable int id, @RequestBody User user) {
		User updatedUser = service.update(id, user);
		if (updatedUser != null) {
			return ResponseEntity.ok().body("Updated user id: " + updatedUser.getId());
		} return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).body(null);
	}

	// http://localhost:8080/users/1
	@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
	public ResponseEntity<String> deleteUser(@PathVariable int id) {
		User removedUser = service.delete(id);
		if (removedUser != null) {
			return ResponseEntity.ok().body("Removed user id: " + removedUser.getId());
		} return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).body(null);
	}
}

Here the meaning of each annotations used:

  • RestController – is a combination of Controller and ResponseBody ( return object as json)
  • Autowired – allows Spring to do a component scan and search for class annotated with @Service. Spring then helps to initialize our class. This is Spring’s DI module.
  • RequestMapping – maps different url pattern and http methods to handler methods.

Rest Application with Spring Boot

Startup project at Spring Initialzr

Select Spring Web Starter and Spring Boot Dev Tools

Import existing Maven Project

Update Maven dependencies at pom.xml

<?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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.0.M4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.davidcheah.springboot</groupId>
	<artifactId>restapi-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>restapi-demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
				<exclusion>
					<groupId>junit</groupId>
					<artifactId>junit</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</pluginRepository>
	</pluginRepositories>

</project>

Add Model

Same as previous

Add Service

Same as previous (with annotation Service)

Add Controller

package com.davidcheah.application.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RestController;

import com.davidcheah.application.services.UserService;
import com.davidcheah.application.exception.UserNotFoundException;
import com.davidcheah.application.model.User;

@RestController
public class UserController {

	@Autowired
	private UserService service;

	//http://localhost:8080/users
	
	@GetMapping("/users")
	public List<User> getAllUsers() {
		List<User> users = service.getAllUsers();
		return users;
	}
	
	@GetMapping("/users/{id}")
	public User getUser(@PathVariable int id) {
		User user = service.getUser(id);
		if(user == null) {
			throw new UserNotFoundException("id-" + id);
		}
		return service.getUser(id);
	}
		
	@PostMapping("/users")
	public ResponseEntity<String> createUser(@RequestBody User user) {
		User newUser = service.add(user);
		if (newUser != null) {
			return ResponseEntity.ok().body("Added user id: " + newUser.getId());
		} return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
	}
	
	@PutMapping("/users/{id}")
	public ResponseEntity<String> updateUser(@PathVariable int id, @RequestBody User user) {
		User updateUser = service.update(id,user);
		if (updateUser != null) {
			return ResponseEntity.ok().body("Updated user id: " + updateUser.getId());
		} return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
	}
	
	@DeleteMapping("/users/{id}")
	public ResponseEntity<String> deleteUser(@PathVariable int id) {
		User removedUser = service.delete(id);
		if (removedUser == null) {
			throw new UserNotFoundException("id-" + id);
		}
		return ResponseEntity.ok().body("Deleted user id: " + removedUser.getId());
	}
}

Here the meaning of each annotations used (almost the same as SpringMVC except we can directly use GetMapping, PostMapping etc) :

  • RestController – is a combination of Controller and ResponseBody ( return object as json)
  • Autowired – allows Spring to do a component scan and search for class annotated with @Service. Spring then helps to initialize our class. This is Spring’s DI module.
  • GetMapping (<HttpMethod>Mapping)- maps different url pattern and http methods to handler methods.

CustomException

We can create our own customized error message that contains that following: timestamp, message and url that the error occur. For this we need a model class for our error.

package com.davidcheah.application.exception;

import java.util.Date;

public class ExceptionResponse {
	private Date timestamp;
	private String message;
	private String details;

	public ExceptionResponse(Date timestamp, String message, String details) {
		super();
		this.timestamp = timestamp;
		this.message = message;
		this.details = details;
	}

	public Date getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(Date timestamp) {
		this.timestamp = timestamp;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getDetails() {
		return details;
	}

	public void setDetails(String details) {
		this.details = details;
	}

}

Next we create a UserNotFoundException extended from RuntimeException. This class should be annotated with ResponseStatus of HttpStatus.NOT_FOUND.

package com.davidcheah.application.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException{

	public UserNotFoundException(String message) {
		super(message);
	}
	
}

Finally we create a customized response entity exception handler, that whenever an exception occurs, we return a response entity with exception response of customized exception.

package com.davidcheah.application.exception;

import java.util.Date;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

	@ExceptionHandler(Exception.class)
	public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
		ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
				request.getDescription(false));
		return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
	}
}

Running our application

In our RestApplication.java, there is a main method that runs the spring application. Run as java application to start the server.

About the author

Founder of tattweicheah.com. Loves music, sport and most importantly software development.

Leave a Reply

Your email address will not be published. Required fields are marked *