1. Overview
In this article, we're going to build a REST API using Spring Boot 2.x and Kotlin. Meanwhile, dedicated support for Kotlin was introduced since Spring Framework 5.0. We can read about the supported features in the official Spring Framework documentation.
In particular, the application will expose data via a REST API and persist data in an embedded H2 database.
2. Use Case
We'll build Restful APIs for an employee information application. A user can create, retrieve, update and delete an employee using this application. An employee has an id, username, first name, last name, email id, and date of birth. Moreover, the username of an employee must be unique.
We'll use an embedded H2 database as our data source along with JPA and Hibernate to access the data from the database.
3. Setup
We can use the Spring Initializer tool to create a Spring Boot application. Besides, we can read about the other ways that we can create a Spring Boot project in the blog post.
Subsequently, we will add Spring Web, Spring Data JPA, H2 Database, Spring Boot Devtools as the dependencies. So now we have all the basic dependencies in the build.gradle.kts
that will allow us to work with Spring Boot and Kotlin:
The Gradle build file also contains some essential plugins:
- The
kotlin-spring
compiler plugin is a wrapper on top of theall-open
plugin. Theall-open
compiler plugin ensures that the Kotlin classes are annotated and their members areopen
. This makes it convenient to use libraries such as Spring AOP that require classes to be open unlike Kotlin classes and their members which are final by default. - The
kotlin-jpa
compiler plugin is a wrapper on top of theno-arg
plugin. Theno-arg
compiler plugin generates a no-argument constructor for classes annotated withEntity
,MappedSuperclass
, andEmbeddable
. This ensures that JPA (Java Persistence API) can instantiate the class since it expects a no-argument constructor defined for its entities.
3.1. Configure Database
We have to configure the H2 database properties so that Spring Boot can create a data source. To define such properties, we can use an external configuration. Furthermore, we can define such external configuration using properties files, YAML files, environment variables, and command-line arguments.
In general, Spring Boot provides the application.properties
file to define such database properties by default. The properties file uses a key-value format.
Alternatively, we can use YAML-based configuration files which use hierarchical data. The YAML files significantly help to avoid repeated prefixes and make is more readable compared to the properties file:
We can also use the application.yml
file to define hibernate properties:
- We set the
ddl-auto
property toupdate
. It will update the database schema based on the modifications in the domain model in our application. This default value iscreate-drop
if we use an embedded database without any schema manager. In case we're using a schema manager such as Liquibase or Flyway, we should consider usingvalidate
. It tries to validate the database schema according to the entities that we have created in the application and throws an error if the schema doesn’t match the entity specifications. - The
show-sql
property enables logging of SQL statement. - The
generate-ddl
property ensures whether to initialize the schema on startup. - The
dialect
property ensures that Hibernate generates better SQL for the chosen database.
4. Domain Model - Kotlin Data class
The domain model is the core part of the application. We can create a domain model Employee
using a data class.
In addition, a data class
in Kotlin automatically generates equals/hashCode
pair, toString
, and copy
functions. Besides, We don't need to define getter and setter methods like Java:
- The
@Entity
annotation specifies that the class is an entity and mapped to a database table. - The
@Table
annotation specifies the name of the database table that is used for mapping. If we use the@Table
annotation without a table name, then Spring generates the table name from the class name. - The
@Id
annotation specifies the property which is the primary key in the entity class. - The
@GeneratedValue
annotation specifies the generation strategies for the values of the primary keys. - The
@Column
annotation specifies the mapped column for a persistent property. If we do not use the@Column
annotation, then Spring generates the column name from the property name.
5. Repository
We're going to create a repository interface to interact with the database. Moreover, the EmployeeRepository
interface will extend from the JpaRepository
interface. This ensures that all the CRUD methods on the Employee
entity are available:
- The
@Repository
annotation specifies that the class is a repository and represents the data access layer in our application.
6. Service
Now, we're going to create a service class that will provide the business logic. Besides, the service layer can interact with the data access layer using JPA.
We inject an instance of the EmployeeRepository
via constructor in EmployeeService
:
- The
@Service
annotation specifies that the class is a service. - The
getAllEmployees()
function can fetch a list of all employees. - The
getEmployeesById()
function can fetch one employee based on the id. We provide the employee id as a parameter to the function. - The
createEmployee()
function can create a new employee. We provide the required properties of the new employee as a parameter to the function. - The
updateEmployeeById()
function can update the employee details based on the id. We provide both the employee id and the properties as parameters to the function. - The
deleteEmployeesById()
function can delete an employee based on the id. We provide the employee id as a parameter to the function.
7. Controller
We implement the APIs for all the CRUD operations in the controller layer which invokes the underlying service.
We define a EmployeeController
as our controller class. In particular, it's a REST controller that provides endpoints for creating, manipulating, and deleting employees.
The EmployeeService
class is wired into the controller to return the values. Also, we reuse the entities as data transfer object for simplicity:
The @RestController
annotation specifies that the class is a controller and capable of handling requests. It combines both the @Controller
and @ResponseBody
annotations.
Spring provides several annotations to handle the different incoming HTTP requests like GET, POST, PUT and DELETE. These annotations are @GetMapping
,@PostMapping
,@PutMapping
, and @DeleteMapping
.
8. Running the application
We can run the application using the following command in the terminal:
gradle bootRun
The Spring Boot application will start running at http://localhost:8080.
9. Exploring the APIs
9.1. Create an Employee
We send the following request to create an employee:
We receive the following response in JSON format:
9.2. Get All Employees
We send the following request to fetch all employees:
We receive the following response in JSON format:
9.3. Get an Employee
We send the following request to fetch an employee based on the employee id:
We receive the following response in JSON format:
9.4. Update an Employee
We send the following request to update employee properties based on the employee id:
We receive the following response in JSON format:
9.5. Delete an Employee
We send the following request to delete an employee based on the employee id:
10. Conclusion
In this tutorial, we looked into creating a microservice application and expose REST API using Kotlin and Spring Boot. In the process, I have also used some best practices which we can utilize while building such applications.
The code for these examples is available on GitHub.
To learn more, check out the related articles on Spring Boot.
Originally published on Anirban's Tech Blog.
Top comments (0)