Part 2: Spring Boot using Kotlin

Erwin Alberto
4 min readJan 22, 2018

--

In this sample application, I will show how to build a Spring Boot application using Kotlin. First, lets get a big picture of what this application is composed of:

  • RestController
  • Service object
  • DAO (Data Access Object) using JDBC
  • Data class
  • Swagger to expose my REST endpoint
  • H2 database with a Hikari CP connection pool in front of it

To set this project up, I used Gradle as the build system. Here is the build.gradle for this project.

group 'com.erwindev.openpayment'
version '1.0'

task wrapper(type: Wrapper) {
gradleVersion = '3.3'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}

buildscript {
ext.kotlin_version = '1.1.2'
ext.springBootVersion = '1.5.9.RELEASE'

repositories {
mavenCentral()
}
dependencies {
// 'kotlin' plugin
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// 'kotlin-spring' plugin
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
// 'spring-boot' plugin
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
// 'cobertura' pugin
classpath "net.saliman:gradle-cobertura-plugin:2.3.1"
}
}

apply plugin: 'kotlin'
apply plugin: 'org.springframework.boot'
apply plugin: 'kotlin-spring'
apply plugin: 'cobertura'

repositories {
mavenCentral()
jcenter()
}

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
compile("org.springframework.boot:spring-boot-starter-jdbc:${springBootVersion}"){
exclude module: 'tomcat-jdbc'
}
compile "com.h2database:h2:1.4.196"
compile "com.zaxxer:HikariCP:2.6.3"
compile "io.springfox:springfox-swagger2:2.7.0"
compile "io.springfox:springfox-swagger-ui:2.7.0"
compile "com.opencsv:opencsv:4.1"
compile "com.google.code.gson:gson:2.8.2"

testCompile "org.springframework.boot:spring-boot-starter-test:${springBootVersion}"
}

jar {
baseName = 'healthcare-openpayment-data'
}

This gives me the following:

  • Kotlin version 1.1.2
  • Spring Boot 1.5.9
  • H2 Database
  • Swagger
  • OpenCSV
  • Google GSON
  • Kotlin Plugin for compiling Kotlin into Java byte code
  • Spring Boot Plugin for creating a Spring Boot application
  • Kotlin-Spring Plugin for interoperability between Kotlin and Spring
  • Cobertura Plugin to calculate test coverage

Since classes in Kotlin are final by default, I need to use the kotlin-spring plugin to allow Kotlin to work with Spring. This plugin helps convert those classes from final to open. Among those classes are the ones annotated by @Configuration as well as methods with @Bean annotation.

Spring Boot entry class

To run the Spring Boot application, I created an application entry point.

package com.erwindev.openpayment

import com.erwindev.openpayment.domain.OpenPayment
import com.erwindev.openpayment.service.OpenPaymentService
import com.erwindev.openpayment.util.ApplicationSettings
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import java.io.FileReader
import com.opencsv.enums.CSVReaderNullFieldIndicator
import com.opencsv.CSVReaderBuilder

/**
* Created by erwinalberto on 1/5/18.
*/
@SpringBootApplication
class Application: CommandLineRunner{

@Autowired
lateinit var applicationSettings: ApplicationSettings

@Autowired
lateinit var openPaymentService: OpenPaymentService

override fun run(args: Array<String>) {
val csvReader = CSVReaderBuilder(FileReader(applicationSettings.paymentFileName))
.withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
// Skip the header
.withSkipLines(1)
.build()


csvReader.forEach{ line ->
var openPayment: OpenPayment = OpenPayment(providerId = line[5],
providerName = line[6] + " " + line[7] + " " + line[8],
paymentAmount = line[30].toDouble(),
payerId = line[26],
payerName = line[27])

openPaymentService.addOpenPayment(openPayment)
}
}
}


fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}

There are a number of things to note in this class.

  • Just like any other Spring Boot application written in Java and Groovy, I am still able to use the Spring Boot annotations in my Kotlin classes. In particular, I am annotating this class with @SpringBootApplication which is a convenient and alternative way to using @Configuration, @EnableAutoConfiguration and @ComponentScan all at the same time.
  • Unlike a Groovy or Java class, Kotlin does not need to define the main function within a class.
  • This class implements the CommandLineRunner which means that the class has to override the run function. In the run function, I am loading a CSV file into an H2 embedded database.
  • Because Spring Framework uses dependency injection techniques to wire up objects in the Spring IoC container, I am able to use the the @Autowired annotation to inject beans need in a class. In this case, Spring Boot is injecting ApplicationSettings and OpenPaymentService in the class. ApplicationSettings contains information from the application.properties file while OpenPaymentService contains the business logic to write the data from CSV file into the H2 database.
  • When performing property injection (using @Autowired) in Kotlin, I have to use the lateinit modifier because non-null types must be initialized in the constructor. Otherwise, I will get a nasty error when I start the application.
  • In order for dependency injection to work, I needed to make sure that application components are annotated with @Component, @Service, @Repository, @Controller,etc. Components that are tagged with those annotations are automatically registered as Spring Beans in the IoC container and are able to be injected in other classes. Additionally, I could have annotated every application component with @Component. However, as you can see in some of the components that I have defined, I am using the more specialized type of @Component (@Service, @Repository or @RestController). This allowed me to perform specific actions with them. For example, @RestController allowed me to define the component as a class that can handle HTTP requests. I will try to explain these annotations later.

In the next part of this tutorial, I will show you how to define the different components of this sample application.

Part 3: Spring Boot Components: Controller, Service, Persistence/DAO

You can find the code this GitHub repo.

--

--