0% found this document useful (0 votes)
153 views7 pages

Kotline

The document discusses building a Kotlin microservice using Spring Boot. It describes including Kotlin dependencies and plugins in Maven, implementing a basic REST controller and model, enabling Spring Boot Actuator endpoints for monitoring, and integrating Swagger API documentation. Configuration files are generated to include version and commit information in the Actuator info endpoint and Swagger documentation.

Uploaded by

tsultim bhutia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
153 views7 pages

Kotline

The document discusses building a Kotlin microservice using Spring Boot. It describes including Kotlin dependencies and plugins in Maven, implementing a basic REST controller and model, enabling Spring Boot Actuator endpoints for monitoring, and integrating Swagger API documentation. Configuration files are generated to include version and commit information in the Actuator info endpoint and Swagger documentation.

Uploaded by

tsultim bhutia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 7

Kotlin Microservice With Spring Boot Tutorial

We walk through building a simple microservice using Kotlin and Spring Boot. It's
the new hotness!

You may find many examples of microservices built with Spring Boot on my blog, but
most of them are written in Java. With the rise in popularity of the Kotlin
language, it is more often used with Spring Boot for building backend services.
Starting with version 5, the Spring framework introduced first-class support for
Kotlin. In this article, I�m going to show you an example of microservices built
with Kotlin and Spring Boot 2. I�ll describe some interesting features of Spring
Boot, which can be treated as a set of good practices when building backend, REST-
based microservices.

1. Configuration and Dependencies


To use Kotlin in your Maven project you have to include plugin kotlin-maven-plugin,
and /src/main/kotlin, /src/test/kotlin directories to the build configuration. We
will also set -Xjsr305 compiler flag to strict. This option is responsible for
checking support for JSR-305 annotations (for example @NotNull annotation).

<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
We should also include some core Kotlin libraries like kotlin-stdlib-jdk8and
kotlin-reflect. They are provided by default for a Kotlin project on
start.spring.io. For REST-based applications, you will also need the Jackson
library for JSON serialization/deserialization. Of course, we have to include
Spring starters for web applications together with Actuator, which is responsible
for providing management endpoints.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>
We use the latest stable version of Spring Boot with Kotlin 1.2.71

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<kotlin.version>1.2.71</kotlin.version>
</properties>
2. Building the Application
Let�s begin with the basics. If you are familiar with Spring Boot and Java, the
biggest difference is in the main class declaration. You will call runApplication
method outside the Spring Boot application class. The main class, the same as in
Java, is annotated with @SpringBootApplication.

@SpringBootApplication
class SampleSpringKotlinMicroserviceApplication
fun main(args: Array<String>) {
runApplication<SampleSpringKotlinMicroserviceApplication>(*args)
}
Our sample application is very simple. It exposes some REST endpoints providing
CRUD operations for the model object. Even with this fragment of code, illustrating
controller implementation, you can see some nice Kotlin features. We may use a
shortened function declaration with an inferred return type. The annotation
@PathVariable does not require any arguments. The input parameter name is
considered to be the same as the variable name. Of course, we are using the same
annotations as with Java. In Kotlin, every property declared as having non-null
type must be initialized in the constructor. So, if you are initializing it using
dependency injection it has to declared as lateinit. Here�s the implementation of
PersonController.

@RestController
@RequestMapping("/persons")
class PersonController {
@Autowired
lateinit var repository: PersonRepository
@GetMapping("/{id}")
fun findById(@PathVariable id: Int): Person? = repository.findById(id)
@GetMapping
fun findAll(): List<Person> = repository.findAll()
@PostMapping
fun add(@RequestBody person: Person): Person = repository.save(person)
@PutMapping
fun update(@RequestBody person: Person): Person = repository.update(person)
@DeleteMapping("/{id}")
fun remove(@PathVariable id: Int): Boolean = repository.removeById(id)
}
Kotlin automatically generates getters and setters for class properties declared as
var. Also if you declare the model as a data class it generates equals, hashCode,
and toString methods. The declaration of our model class Personis very concise as
shown below.

data class Person(var id: Int, var name: String, var age: Int, var gender: Gender)
I have implemented my own in-memory repository class. I use Kotlin extensions for
manipulating the list of elements. This built-in Kotlin feature is similar to Java
streams, with the difference that you don�t have to perform any conversion between
Collection and Stream.

@Repository
class PersonRepository {
val persons: MutableList<Person> = ArrayList()
fun findById(id: Int): Person? {
return persons.singleOrNull { it.id == id }
}
fun findAll(): List<Person> {
return persons
}
fun save(person: Person): Person {
person.id = persons.size + 1
persons.add(person)
return person
}
fun update(person: Person): Person {
val index = persons.indexOf(person)
persons[index] = person
return person
}
fun removeById(id: Int): Boolean {
return persons.removeIf { it.id == id }
}
}
The sample application source code is available on the GitHub in repository, here.

3. Enabling Actuator Endpoints


Since we have already included Spring Boot starter with Actuator in the application
code, we can take advantage of its production-ready features. Spring Boot Actuator
gives you very powerful tools for monitoring and managing your apps. You can
provide advanced health checks, info endpoints, or send metrics to numerous
monitoring systems like InfluxDB. After including Actuator artifacts, the only
thing we have to do is to enable all its endpoint for our application via HTTP.

management.endpoints.web.exposure.include: '*'

We can customize Actuator endpoints to provide more details about our app. A good
practice is to expose information about the version and git commit to the info
endpoint. As usual, Spring Boot provides auto-configuration for such features, so
the only thing we need to do is to include some Maven plugins to the build
configuration in pom.xml. The goal, build-info, is set for spring-boot-maven-plugin
and forces it to generate a properties file with basic information about the
version. The file is located in the directory, META-INF/build-info.properties. The
plugin git-commit-id-plugin will generate a git.propertiesfile in the root
directory.

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration>
</plugin>
Now you should just build your application using mvn clean installcommand and then
run it.

$ java -jar target\sample-spring-kotlin-microservice-1.0-SNAPSHOT.jar

The info endpoint is available under address http://localhost:8080/actuator/info.


It exposes some interesting information for us.

{
"git":{
"commit":{
"time":"2019-01-14T16:20:31Z",
"id":"f7cb437"
},
"branch":"master"
},
"build":{
"version":"1.0-SNAPSHOT",
"artifact":"sample-spring-kotlin-microservice",
"name":"sample-spring-kotlin-microservice",
"group":"pl.piomin.services",
"time":"2019-01-15T09:18:48.836Z"
}
}
4. Enabling API Documentation
Build info and git properties may be easily injected into the application code. It
can be useful in some cases. One of those cases is if you have enabled auto-
generated API documentation. The most popular tools for this is Swagger. You can
easily integrate Swagger 2 with Spring Boot using the SpringFox Swagger project.
First, you need to include the following dependencies to your pom.xml.

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Then, you should enable Swagger by annotating the configuration class with
@EnableSwagger2. The required information is available inside the beans,
BuildProperties and GitProperties. We just have to inject them into the Swagger
configuration class as shown below. We set them as optional to prevent application
startup failure in case they are not present on the class path.

@Configuration
@EnableSwagger2
class SwaggerConfig {
@Autowired
lateinit var build: Optional<BuildProperties>
@Autowired
lateinit var git: Optional<GitProperties>
@Bean
fun api(): Docket {
var version = "1.0"
if (build.isPresent && git.isPresent) {
var buildInfo = build.get()
var gitInfo = git.get()
version = "${buildInfo.version}-${gitInfo.shortCommitId}-$
{gitInfo.branch}"
}
return Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(version))
.select()
.apis(RequestHandlerSelectors.any())
.paths{ it.equals("/persons")}
.build()
.useDefaultResponseMessages(false)
.forCodeGeneration(true)
}
@Bean
fun uiConfig(): UiConfiguration {
return UiConfiguration(java.lang.Boolean.TRUE, java.lang.Boolean.FALSE, 1,
1, ModelRendering.MODEL, java.lang.Boolean.FALSE, DocExpansion.LIST,
java.lang.Boolean.FALSE, null, OperationsSorter.ALPHA, java.lang.Boolean.FALSE,
TagsSorter.ALPHA, UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS, null)
}
private fun apiInfo(version: String): ApiInfo {
return ApiInfoBuilder()
.title("API - Person Service")
.description("Persons Management")
.version(version)
.build()
}
}
The documentation is available under the context path,/swagger-ui.html. Besides API
documentation, it displays the information about the application version, git
commit id, and branch name.

Image title

5. Choosing Your App Server


Spring Boot Web can be run on three different embedded servers: Tomcat, Jetty, or
Undertow. By default, it uses Tomcat. To change the default server, you just need
to include the suitable Spring Boot starter and exclude spring-boot-starter-tomcat.
A good practice may be to enable switching between servers during application
build. You can achieve it by declaring Maven profiles as shown below.

<profiles>
<profile>
<id>tomcat</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>jetty</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>undertow</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
Now, if you would like to enable servers other than Tomcat for your application,
you should activate the appropriate profile during the Maven build.

$ mvn clean install -Pjetty

Conclusion
The development of microservices using Kotlin and Spring Boot is nice and simple.
Based on this sample application, I have introduced the main Spring Boot features
for Kotlin. I also described some good practices you may apply to your
microservices when building them using Spring Boot and Kotlin. You can compare the
described approach with some other micro-frameworks used with Kotlin, for example,
Ktor, described in one of my previous articles: Kotlin Microservices with Ktor.

You might also like