As part of this post, we will learn how to write a CRUD Rest API using Spring Boot. Spring boot provides some cool features to create a production-ready Spring application that can be deployed as a war file on any environment. This will be a series of posts, but we will start with the creation of a simple REST API.
What you’ll need
- Eclipse Mars.2 Release
- Java version 1.8
- MySQL 5.0 or higher
- Maven 3.0 or higher
What we’ll cover
In this article, we will cover the following items
- Create a Maven project
- Assemble pom file for all dependencies
- Create entity classes
- Business logic to handle data
- A REST controller
- Run the API in tomcat
Create a Maven project
As the first step, let’s create a maven project in eclipse. You can create this by going into File > New > Maven Project.
Select an Archtype
as maven-archtype-webapp
.
Enter artifactid as benefits and groupid as com.betterjavacode
Assemble pom file for all dependencies
We will be using spring-boot and all the required dependencies including spring-data. Spring data JPA provides a lot of useful enhancements that you can seamlessly use with spring-boot project. Spring-data will cover the data access layer which basically implements persistence. Once we use spring-data, we don’t have to add any external hibernate
or eclipselink
JPA APIs. Also, some of the data access repositories provided by spring-data make implementing data access layer code less worrisome.
<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.betterjavacode</groupId> <artifactId>Benefits</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Benefits Maven Webapp</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> <finalName>Benefits</finalName> </build> </project>
Create entity classes
We will be creating a rest API for Benefits service which will have companies and users as main objects. We are only covering basic data model classes at the moment, but as part of the series, we will develop a web application. Each company will have a company profile and each user will user profile. So we will have four basic entities Company, CompanyProfile, User, UserProfile.
package com.betterjavacode.benefits.entities; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity(name = "Company") @Table(name = "company") public class Company implements Serializable { /** * */ private static final long serialVersionUID = 1L; public Company() { } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column private String name; @Column private int statusid; @OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) @JoinColumn(name = "companyprofileid") private CompanyProfile cp; @Column private String type; @Column private String ein; 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 int getStatusid() { return statusid; } public void setStatusid(int statusid) { this.statusid = statusid; } public CompanyProfile getCp() { return cp; } public void setCp(CompanyProfile cp) { this.cp = cp; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getEin() { return ein; } public void setEin(String ein) { this.ein = ein; } }
package com.betterjavacode.benefits.entities; import java.io.Serializable; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity(name = "User") @Table(name = "user") public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; public User() { } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column private Date createdate; @Column private String email; @Column private String firstname; @Column private String middlename; @Column private String lastname; @Column private String username; @Column private String jobtitle; @OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) @JoinColumn(name = "userprofileid") private UserProfile userprofile; public int getId() { return id; } public void setId(int id) { this.id = id; } public Date getCreatedate() { return createdate; } public void setCreatedate(Date createdate) { this.createdate = createdate; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getMiddlename() { return middlename; } public void setMiddlename(String middlename) { this.middlename = middlename; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getJobtitle() { return jobtitle; } public void setJobtitle(String jobtitle) { this.jobtitle = jobtitle; } public UserProfile getUserprofile() { return userprofile; } public void setUp(UserProfile up) { this.userprofile = up; } }
Business logic to handle the data
Part of our architecture for REST API, we will have the following three layers
- Rest layer
- Business object layer
- Data access layer
So in the Business object layer, we will implement all the managers which will handle the processing of rest requests to create, update, read, or delete the data. In subsequent posts, we will enhance this layer to handle logging, error handling, and more.
package com.betterjavacode.benefits.managers; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import com.betterjavacode.benefits.entities.User; import com.betterjavacode.benefits.interfaces.UserManager; import com.betterjavacode.benefits.repositories.UserRepository; public class UserManagerImpl implements UserManager { private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } @Override public User createUser(User u) { if (u != null) { User user = userRepository.save(u); return user; } else { return null; } } @Override public User updateUser(User u) { // TODO Auto-generated method stub return null; } @Override public User getUser(int id) { User user = userRepository.findOne(id); if (user == null) { return null; } return user; } @Override public List getAllUsers() { List userList = (List) userRepository.findAll(); return userList; } @Override public void deleteUser(int guid) { // TODO Auto-generated method stub User user = userRepository.findOne(guid); if (user == null) { return; } userRepository.delete(user); } }
A REST controller
One of the best uses of Spring boot is to create rest API and the feature it offers for the same is to use the REST controller. Spring-boot offers an annotation for the same as @RestController
.
package com.betterjavacode.benefits.controller; import java.util.List; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.betterjavacode.benefits.entities.User; import com.betterjavacode.benefits.interfaces.UserManager; @RestController @RequestMapping("benefits/v1") public class UserService { @Autowired UserManager userMgr; @RequestMapping(value = "/users/", method = RequestMethod.POST) public User createUser(User user) { User u = userMgr.createUser(user); return u; } @RequestMapping(value = "/users/{id}", method = RequestMethod.GET) public User getUser(@PathVariable("id") int id) { User u = userMgr.getUser(id); return u; } @RequestMapping(value = "/users/", method = RequestMethod.GET) public List getAllUsers() { List cList = userMgr.getAllUsers(); return cList; } @RequestMapping(value = "/users/", method = RequestMethod.PUT) public User updateUser(User user) { User u = userMgr.updateUser(user); return u; } @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE) public Response deleteUser(@PathVariable("id") int id) { userMgr.deleteUser(id); return Response.status(Response.Status.OK) .build(); } }
package com.betterjavacode.benefits.controller; import java.util.List; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.betterjavacode.benefits.entities.Company; import com.betterjavacode.benefits.interfaces.CompanyManager; @RestController @RequestMapping("benefits/v1") public class CompanyService { @Autowired CompanyManager compMgr; @RequestMapping(value = "/companies/", method = RequestMethod.POST) public Company createCompany(Company company) { Company c = compMgr.createCompany(company); return c; } @RequestMapping(value = "/companies/{id}", method = RequestMethod.GET) public Company getCompany(@PathVariable("id") int id) { Company c = compMgr.getCompany(id); return c; } @RequestMapping(value = "/companies/", method = RequestMethod.GET) public List getAllCompanies() { List cList = compMgr.getAllCompanies(); return cList; } @RequestMapping(value = "/companies/", method = RequestMethod.PUT) public Company updateCompany(Company company) { Company c = compMgr.updateCompany(company); return c; } @RequestMapping(value = "/companies/{id}", method = RequestMethod.DELETE) public Response deleteCompany(@PathVariable("id") int id) { compMgr.deleteCompany(id); return Response.status(Response.Status.OK) .build(); } }
Run the API in tomcat
We are using embedded tomcat in this Spring-boot project. So once we are done building and installing the code through maven, we can run the project through eclipse or standalone war file in tomcat. For our demo purposes, we will run this application through the eclipse, which will start embedded tomcat.
If we execute the URL http://localhost:8080/benefits/v1/users/1
– it will display JSON for user data as below
You can find the source code for this project Github Repository.
Pingback: Error Handling and Logging in Spring Boot REST API – Part III | Code Junkie
Pingback: Consuming a RESTful Webservice – Part IV | Code Junkie
Pingback: Producing and Consuming SOAP Webservice with Spring Boot – Part V | Code Junkie
Pingback: Design Patterns – Factory Pattern – Part III | Code Complete
Pingback: How to use Spring Boot Security in web application – Part VIII | Code Complete
Pingback: How to deploy Spring Boot Application on docker – Part IX | Code Complete