DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Migration of Microservice Applications From WebLogic to Openshift
  • Google Cloud Pub/Sub: Messaging With Spring Boot 2.5
  • Spring Boot Microservices + Apache Camel: A Hello World Example

Trending

  • Integration Isn’t a Task — It’s an Architectural Discipline
  • Integrating Model Context Protocol (MCP) With Microsoft Copilot Studio AI Agents
  • Metrics at a Glance for Production Clusters
  • Manual Sharding in PostgreSQL: A Step-by-Step Implementation Guide
  1. DZone
  2. Coding
  3. Frameworks
  4. Kotlin Microservice With Spring Boot Tutorial

Kotlin Microservice With Spring Boot Tutorial

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

By 
Piotr Mińkowski user avatar
Piotr Mińkowski
·
Jan. 22, 19 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
35.8K Views

Join the DZone community and get the full member experience.

Join For Free

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.

Spring Framework Spring Boot Kotlin (programming language) microservice application

Opinions expressed by DZone contributors are their own.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Migration of Microservice Applications From WebLogic to Openshift
  • Google Cloud Pub/Sub: Messaging With Spring Boot 2.5
  • Spring Boot Microservices + Apache Camel: A Hello World Example

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: