Build REST CRUD API's with Kotlin, Spring, Spring Data JPA, and RDBMS
In this article, we will show you how to develop a REST-style web service with Kotlin, Spring Boot, H2DB.
A quick overview of Kotlin, Spring Boot, and H2DB
Kotlin
Kotlin is a statically typed, general-purpose programming language targeting the Java platform. Kotlin is concise, safe, pragmatic, and fixated on interoperability with Java code. It can be used virtually everywhere Java is utilized today: for server-side development, Android apps, and much more. Kotlin works great with all subsisting Java libraries and frameworks and runs with the same level of performance as Java.
H2DB[RDBMS]
H2DB is a relational database management system written in Java. It can be embedded in Java applications or run in client-server mode.
Spring Boot
Spring boot to develop REST web services and microservices. Spring Boot has taken the Spring framework to the next level. It has drastically reduced the configuration and setup time required for spring projects. We can set up a project with almost zero configuration and start building the things that actually matter to your application.
Technologies used :
- Spring Boot 2.3.7.RELEASE
- Spring 5.2.12.RELEASE
- Kotlin 2.11.3
- Hibernate 5.4.25.Final
- H2DB
- Maven 3
- Java 8
After completing this tutorial what we will build?
We will build REST API CRUD features:
- GET - Fetch all User : /api/v1/users
- GET - Get User by ID : /api/v1/users/{id}
- POST - Create User : /api/v1/users
- PUT - Edit User Details : /api/v1/users/{id}
- DELETE - Delete User : /api/v1/users/{id}
Project Directory
Maven[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
https://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.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev</groupId>
<artifactId>kotlin_springb_postgresql_restful_api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>kotlin_springb_postgresql_restful_api</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<kotlin.version>1.3.72</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</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>
</exclusions>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
<plugin>jpa</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Creating the Entity[User.kt]
package com.knf.dev.entity
import javax.persistence.*
@Entity
@Table(name = "user")
data class User(
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: Long,
val firstName: String,
val lastName: String,
val emailId: String
)
Creating the Repository[UserRepository.kt]
package com.knf.dev.repository
import com.knf.dev.entity.User
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface UserRepository : JpaRepository<User, Long>
Creating the controller End-points[UserController.kt]
package com.knf.dev.controller
import com.knf.dev.entity.User
import com.knf.dev.repository.UserRepository
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/v1/")
class UserController(private val userRepository: UserRepository) {
@GetMapping("/users")
fun getAllUsers(): List<User> =
userRepository.findAll()
@PostMapping("/users")
fun createNewUser(@RequestBody user: User): User =
userRepository.save(user)
@GetMapping("/users/{id}")
fun getUserById(@PathVariable(value = "id") userId: Long):
ResponseEntity<User> {
return userRepository.findById(userId).map { usr ->
ResponseEntity.ok(usr)
}.orElse(ResponseEntity.notFound().build())
}
@PutMapping("/users/{id}")
fun updateUserById(@PathVariable(value = "id") userId: Long,
@RequestBody newUser: User):
ResponseEntity<User> {
return userRepository.findById(userId).map { existingUser ->
val updatedEmployee: User = existingUser
.copy(firstName = newUser.firstName, lastName =
newUser.lastName, emailId = newUser.emailId)
ResponseEntity.ok().body(userRepository.save(updatedEmployee))
}.orElse(ResponseEntity.notFound().build())
}
@DeleteMapping("/users/{id}")
fun deleteUserById(@PathVariable(value = "id") userId: Long):
ResponseEntity<Void> {
return userRepository.findById(userId).map { usr ->
userRepository.delete(usr)
ResponseEntity<Void>(HttpStatus.OK)
}.orElse(ResponseEntity.notFound().build())
}
}
Main[KotlinSpringbH2DBRestfulApiApplication.tk]
package com.knf.dev
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class KotlinSpringbH2DBRestfulApiApplication
fun main(args: Array<String>) {
runApplication<KotlinSpringbH2DBRestfulApiApplication>(*args)
}
Run
$ mvn spring-boot:run
Testing API's using Postman
Create an User
Delete User By Id