REST API in Kotlin & Spring Boot

Senior Full-Stack Developer with over 20 years of experience building web applications for startups, government, and higher education.
Search for a command to run...

Senior Full-Stack Developer with over 20 years of experience building web applications for startups, government, and higher education.
No comments yet. Be the first to comment.
Writing this up so I have somewhere to quickly grab basic Jest setup. This information is copied from the Jest Documentation Site compressed into just the parts I'm interested in. Create folders mkdir -p <project>/src cd <project> Install and init n...

In this blog post, we'll explore the process of setting up and configuring a Postgres database using Docker and seeding it with test data. This approach can be used for a variety of apps and can be easily adapted for your own needs. We'll cover all t...

Continuing from last time, we will explore the concepts behind Create and Update functionality and provide a step-by-step guide on how to implement it in your SvelteKit application. Let's get started! Server & Client Code In SvelteKit, the server-sid...

Introduction Welcome to the latest post in my series of Koan Battles using Kotlin and TypeScript. In this series, we'll complete a Koan in both languages and then discuss the differences between the two solutions. My goal is to help you gain a deeper...

In this post, I will explore how to create a REST API using Spring Boot and Kotlin. We will dive into the fundamentals of Spring Boot and Kotlin, explain how to set up the project, and guide you through the process of building the API step by step. By the end of this blog post, you should have a solid understanding of how to create a robust and scalable CRUD API following the RESTful principles in Spring Boot and Kotlin.
We'll build an API to the Daily Top 3 database that I've blogged about previously.
We'll use the spring initializr website to create the project:

Then add the following dependencies to the build.gragle.kts file:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.postgresql:postgresql")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
We need two entities for our domain Top3 and Todo:
@Entity
@Table(name = "top3")
data class Top3(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
@Column(name = "created_at", nullable = false)
val createdAt: LocalDate = LocalDate.now(),
@OneToMany(mappedBy = "top3", cascade = [CascadeType.ALL], orphanRemoval = true)
@JsonManagedReference
val todos: MutableList<Todo> = mutableListOf()
)
@Entity
@Table(name = "todo")
data class Todo(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0,
@Column(name = "title", nullable = false)
val title: String,
@Column(name = "complete", nullable = false)
var complete: Boolean,
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="top3_id")
@JsonBackReference
var top3: Top3
)
We use annotations such as @Entity, @Table, @Id, @GeneratedValue, @Column, etc. to map our Kotlin classes to the database tables. We also define relationships between our entities using annotations such as @OneToMany and @ManyToOne.
JPA repositories provide an easy way to perform CRUD (Create, Read, Update, Delete) operations on your entities. To create a JPA repository for the Top3 entity, you can create an interface that extends JpaRepository and specify the entity type and primary key type as generic parameters. It's as simple as:
interface Top3Repository : JpaRepository<Top3, Long> {}
Once this interface is defined, Spring Data JPA will automatically generate implementations at runtime. You can then use the repository to perform CRUD operations on your entities.
A Spring MVC controller is responsible for handling HTTP requests and generating responses. To create a controller for the Top3 entity, you can create a class annotated with @RestController and define methods to handle different HTTP requests. Here’s an example:
@RestController
@RequestMapping("/top3")
class Top3Controller(private val top3Repository: Top3Repository) {
@GetMapping
fun findAll(): Top3Dto = top3Repository.findByCreatedAt(LocalDate.now()).toDto()
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@RequestBody top3Dto: Top3Dto): Top3Dto {
val top3 = Top3()
top3Dto.todos.map { top3.todos += it.toEntity(top3) }.toMutableList()
return top3Repository.save(top3).toDto()
}
@PutMapping("/{id}")
fun update(@PathVariable id: Long, @RequestBody top3Dto: Top3Dto): Top3 {
val existingTop3 = top3Repository.findById(id).orElseThrow { EntityNotFoundException() }
val updatedTodos = top3Dto.todos.map { it.toEntity(existingTop3) }.toMutableList()
val updatedTop3 = existingTop3.copy(todos = updatedTodos)
return top3Repository.save(updatedTop3)
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun delete(@PathVariable id: Long) {
top3Repository.deleteById(id)
}
}
In this example, we use annotations such as @RestController, @RequestMapping, @GetMapping, @PostMapping, etc. to define our controller and map its methods to different HTTP requests. We also use the Top3Repository to perform CRUD operations on our entities.
We can now run the app and try out the API with a few curl commands:
# CREATE
curl -X POST \
http://localhost:8080/top3 \
-H 'Content-Type: application/json' \
-d '{
"createdAt": "2022-01-01",
"todos": [
{
"title": "Create Todo",
"complete": false
},
{
"title": "Write article",
"complete": false
},
{
"title": "Publish article",
"complete": false
}
]
}'
# READ
curl http://localhost:8080/top3
{
"id":1,
"createdAt":"2023-03-14",
"todos":[
{"id":1,"title":"Updated Todo","complete":true},
{"id":2,"title":"Write article","complete":true},
{"id":3,"title":"Publish article","complete":true}
]
}
# UPDATE
curl -X POST \
http://localhost:8080/top3 \
-H 'Content-Type: application/json' \
-d '{
"createdAt": "2022-01-01",
"todos": [
{
"title": "Updated Todo",
"complete": true
},
{
"title": "Write article",
"complete": false
},
{
"title": "Publish article",
"complete": false
}
]
}'
# DELETE
curl -X DELETE http://localhost:8080/top3/1
In this blog post, we have learned how to create a REST API using Spring Boot and Kotlin. We have covered the basics of Spring Boot and Kotlin, how to set up the project, and how to implement the CRUD operations for the Daily Top 3 database.
This API is not the end of our journey, but rather the beginning. In future posts, we will explore how to create Web and Mobile frontends that consume this API and display the data in different ways.
If you want to see the full code of this project or try it out yourself, you can find it on GitHub. Thank you for reading!