Implemented Spring Boot RESTful API with Kotlin

If you are planning to implement Java applications from now on, we recommend Spring Boot with Kotlin. This time I will briefly introduce the implementation of RESTful CRUD server using these two. Source code is released to github so please refer.

https://github.com/tomokazukozuma/ToDoAppForKotlin

Environment

  • Mac OS X
  • Eclipse Pleiades All in One 4.7.0
  • Java 8
  • Kotlin 1.1.3
  • Spring Boot 1.5.4.RELEASE

Procedure

  1. Establishment of Kotlin’s environment using Eclipse
  2. Migrating MySQL using Flyway
  3. Folder structure
  4. Writing Controller
  5. Writing Entity
  6. Writing Repository

1. Establishment of Kotlin’s environment using Eclipse

This time we will use Eclipse, a highly functional IDE with a free IDE. Spring Boot can start the project with the function called the Spring starter project, introducing the minimum necessary functions. This time we will first select the functions web, JPA, MySQL, Flyway.
Please refer to the following article for details of environment construction.

http://tomokazu-kozuma.com/how-to-build-environment-of-eclipse-spring-boots-and-kotlin/

2. Migrating MySQL using Flyway

After completing the environment construction, we will prepare the DB after completion. We use Flyway for DB migration. It is recommended because we do not have to install anything else before installation is so easy and easy to use.
For details of Flyway please refer to the following article.

http://tomokazu-kozuma.com/how-to-migrate-mysql-using-flyway/

The tables to be created this time are the following two. Please set this table to be created with Flyway. Let the DB name be todoapp.

CREATE DATABASE todoapp;
USE todoapp;
CREATE TABLE todo
CREATE TABLE user

3. Folder structure

For reference, the folder structure is as follows.

4. Writing Controller

Since it is a RESTful API that returns json, there is no view related processing. So I am using @RestController and returning json.

package com.todoapp.controller
import com.todoapp.facade.ToDoFacade
import com.todoapp.requestformat.todo.AddToDoRequestFormat
import com.todoapp.requestformat.todo.GetToDoRequestFormat
import com.todoapp.requestformat.todo.UpdateToDoTextRequestFormat
import com.todoapp.responseformat.todo.AddToDoResponseFormat
import com.todoapp.responseformat.todo.DeleteToDoResponseFormat
import com.todoapp.responseformat.todo.ToDoResponseFormat
import com.todoapp.responseformat.todo.UpdateToDoCompleteFlagResponseFormat
import com.todoapp.responseformat.todo.UpdateToDoTextResponseFormat
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
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.ResponseStatus
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/todo")
class ToDoController @Autowired constructor(private val todoFacade: ToDoFacade) {
    @GetMapping
fun getToDoList(@ModelAttribute requestFormat: GetToDoRequestFormat): ToDoResponseFormat {
return todoFacade.getToDo(requestFormat.userId)
}
    @PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun addToDo(@RequestBody requestFormat: AddToDoRequestFormat): AddToDoResponseFormat {
return todoFacade.addToDo(requestFormat.userId, requestFormat.text)
}
    @RequestMapping(value = "{id:^[0-9]+$}", method = arrayOf(RequestMethod.PATCH))
fun updateToDoText(@PathVariable id: Int, @RequestBody requestFormat: UpdateToDoTextRequestFormat): UpdateToDoTextResponseFormat {
return todoFacade.updateToDoText(id, requestFormat.text)
}
    @RequestMapping(value = "{id:^[0-9]+$}/complete", method = arrayOf(RequestMethod.PATCH))
fun updateToDoCompleteFlag(@PathVariable id: Int): UpdateToDoCompleteFlagResponseFormat {
return todoFacade.updateToDoCompleteFlag(id)
}
    @RequestMapping(value = "{id:^[0-9]+$}", method = arrayOf(RequestMethod.DELETE))
fun deleteToDo(@PathVariable id: Int): DeleteToDoResponseFormat {
return todoFacade.deleteToDo(id)
}
}

5. Writing Entity

Entity basically only holds data, so write using Kotlin’s data class. When declaring with var, getter is generated by declaring setter and getter with val. In the data class, simply setting properties in the primary constructor produces the following.

  • Equals () / hashCode ()
  • Show instance properties toString ()
  • Extract contents in declaration order componentN ()
  • Copy ()
package com.todoapp.entity
import com.fasterxml.jackson.annotation.JsonIgnore
import java.sql.Timestamp
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.Table
    @Entity
@Table(name = "todo")
data class ToDo (
    @Id
@GeneratedValue
var id: Int = 0,
    @Column(name = "user_id", nullable = false)
var userId: Int = 0,
    @Column(nullable = false)
var text: String = "",
    @Column(name = "complete_flag", nullable = false)
var completeFlag: Boolean = false,
    @Column(name = "complete_datetime", nullable = true)
var completeDatetime: Timestamp? = null,
    @JsonIgnore
@Column(name = "insert_datetime", nullable = false)
var insertDatetime: Timestamp = Timestamp(0),
    @JsonIgnore
@Column(name = "update_datetime", nullable = false)
var updateDatetime: Timestamp = Timestamp(0),
    @JsonIgnore
@Column(name = "delete_flag", nullable = false)
var deleteFlag: Boolean = false
)

6. Writing Repository

Even if I write it in Java, the Repository will not change so much.

package com.todoapp.repository
import com.todoapp.entity.ToDo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional
@Repository
interface ToDoRepository : JpaRepository<ToDo, Long> {
    fun findOneById(id: Int): ToDo
    fun findByUserId(userId: Int): MutableList<ToDo>
    @Transactional
@Modifying
@Query("UPDATE ToDo AS t SET t.text = :text WHERE t.id = :id")
fun updateTextById(@Param("id") id: Int, @Param("text") text: String) : Int
    @Transactional
@Modifying
@Query("UPDATE ToDo AS t SET t.completeFlag = true, completeDatetime = NOW() WHERE t.id = :id")
fun updateCompleteFlagById(@Param("id") id: Int) : Int
}

Summary

I just introduced a bit of the source code, but with a simple Restful API it took a while without strain. People using Java please take this opportunity to try Kotlin.