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 Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
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
Partner Zones AWS Cloud
by AWS Developer Relations
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
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • Getting Started With Istio in AWS EKS for Multicluster Setup
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • Event-Driven Architecture Using Serverless Technologies
  • Integrating AWS With Salesforce Using Terraform

Trending

  • Getting Started With Istio in AWS EKS for Multicluster Setup
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • Event-Driven Architecture Using Serverless Technologies
  • Integrating AWS With Salesforce Using Terraform
  1. DZone
  2. Coding
  3. Frameworks
  4. Tutorial: Reactive Spring Boot Part 1, Building a Kotlin REST Service

Tutorial: Reactive Spring Boot Part 1, Building a Kotlin REST Service

Learn how to create a Spring Boot Kotlin REST service!

Trisha Gee user avatar by
Trisha Gee
·
Nov. 15, 19 · Tutorial
Like (15)
Save
Tweet
Share
19.81K Views

Join the DZone community and get the full member experience.

Join For Free

REST service

Get some REST!

Last month, I presented a live demo at SpringOne Platform, showing how to build a Spring Boot application that displays real-time prices, using Spring (obviously), Kotlin, and JavaFX. The live demo was recorded and is available as a 70-minute video, but I thought it might be easier to digest as a series of shorter videos with an accompanying blog post, explaining each of the steps more slowly and in more detail.

This is the first step: creating a reactive Spring Boot service with Kotlin.

You may also like: Fully Reactive: Spring, Kotlin, and JavaFX Playing Together [Links]

This blog post contains a video showing the process step-by-step and a textual walk-through (adapted from the transcript of the video) for those who prefer a written format.


This tutorial is a series of steps during which we will build a full Spring Boot application featuring a Kotlin back-end, a Java client, and a JavaFX user interface.

This first step in the tutorial is to create a Kotlin Spring Boot application, which serves as the back-end of the application. We'll create a REST service that can be connected to in later parts of the tutorial.

Create a Spring Boot Service

Let's create a new project for our Spring Boot service.

  1. Select New Project, either from the menu of IntelliJ IDEA or from the start screen.
  2. Select the Spring Initializr option on the left of the New Project window.
  3. We're using Java 13 as the SDK for this tutorial, although we're not using any of the Java 13 features (you can download JDK 13.0.1 here, then define a new IntelliJ IDEA SDK for it).
  4. Enter the group name for the project, and we'll use stock-server as the name.
  5. We can build this project with Maven or Gradle. We're going to create a Maven project that will generate the pom.xml and Maven wrapper files that we need.
  6. Choose Kotlin as the language. We'll select Java 11 as the Java version as this is the most recent Long Term Support version for Java, but for the purposes of this project, it makes no difference.
  7. The project name is automatically populated from the artifact name, we don't need to change this.
  8. Add a useful description of the project.
  9. We can optionally change the top-level package if we need to.

Next, we select the Spring Boot Starters we need.

  1. Choose which version of Spring Boot to use. We're going to use 2.2.0 RC1 for this tutorial because later we'll be using features that are only available in the release candidate.
  2. We can search for and select which Spring Boot starters we want to use. This is a reactive REST service, so select Reactive Web.
  3. We'll use the defaults for the project name and location.

IntelliJ IDEA will use Spring Initializr to create the project and then import it correctly into the IDE. Enable auto-import on Maven so when we make changes to the pom.xml file, the project dependencies will automatically be refreshed.

The Spring Boot Project

In the project window, we see the structure of the project that has been created, including a Kotlin directory and the standard default Application class that Spring Boot creates.

package com.mechanitis.demo.stockservice

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class StockServiceApplication

fun main(args: Array<String>) {
    runApplication<StockServiceApplication>(*args)
}


IntelliJ IDEA Ultimate has full support for Spring applications, which includes gutter icons making it easier to identify and navigate between Spring elements like Spring Beans.

If we take a quick look at the generated pom.xml file, we see not only the selected Spring Boot starters and Kotlin dependencies, we can also see the Spring compiler plugin in the kotlin-maven-plugin. This makes it a bit simpler to work with Spring in Kotlin.

Run this basic application using the shortcut Ctrl+Shift+F10 for Windows or Linux (⌃⇧R for macOS) from inside the Application class file, or double-press Ctrl ("run anything") and type "StockServiceApplication" to run the application. It should start successfully, with Netty running on port 8080. Stop it with Ctrl+F2 (⌘F2).

Create a REST Controller

Now that we know it all works, we can get started on our own functionality.

  1. Create a class for our REST Controller. We'll put it in the same Kotlin file to keep things simple for now.
  2. We need to annotate this as a  @RestController.
  3. (Tip: we can use Live Templates to create code faster. We can type "fun1" and press tab to create a function that takes a single argument).
  4. Create a function "prices" which takes the symbol of the stock we want to get the prices for. This method will return Flux<StockPrice>, which will be a constant stream of prices.
@RestController
class RestController() {
    fun prices(@PathVariable symbol: String): Flux<StockPrice> {

    }
}


Create a Data Class for Stock Price

  1. (Tip: We can get IntelliJ IDEA to create the StockPrice class by pressing Alt+Enter on the red StockPrice symbol and selecting "Create class StockPrice")
  2. Create a StockPrice class inside this same Kotlin file.
  3. This is going to be Kotlin data class. This is a compact way to declare a class with properties, and we simply declare what we want in the Constructor parameters. We want a symbol for the stock, which is a String, a price, which is a Double, and the time associated with that price, using Java 8's java.time.LocalDateTime.
data class StockPrice(val symbol: String,
                      val price: Double,
                      val time: LocalDateTime)


Generate and Return Prices

Now we're going to define what the prices method returns. This method is going to create a Flux, which emits one randomly generated price every second. We can do this with an interval with a Duration of one second.

  fun prices(symbol: String): Flux<StockPrice> {
        return Flux.interval(Duration.ofSeconds(1))
    }


(Note: This code will not compile yet)

Then, we can create a new StockPrice for each of these seconds. Note that in Kotlin, we don't need the "new" keyword. The StockPrice needs the symbol, a price, which for the purposes of this tutorial will be randomly generated, and a time, which will be "now".

    fun prices(symbol: String): Flux<StockPrice> {
        return Flux
                .interval(Duration.ofSeconds(1))
                .map { StockPrice(symbol, randomStockPrice(), LocalDateTime.now()) }
    }


(Note: This code will not compile yet)

Create this randomStockPrice function (we can use Alt+Enter to automatically create it). One way to create an arbitrary Double is using ThreadLocalRandom and the nextDouble method. Let's generate a number between zero and one hundred.

  private fun randomStockPrice(): Double {
        return ThreadLocalRandom.current().nextDouble(100.0)
    }


Since we want to be able to access the prices method via an HTTP Get call, we need to add the @GetMapping annotation to it. It needs a path ("/stocks/{symbol}"), and we need to define what the response to this method looks like. We're going to use TEXT_EVENT_STREAM_VALUE to create a server-sent events streaming endpoint. We need to also declare our symbol parameter as a @PathVariable.

The whole RestController now looks like:

@RestController
class RestController() {
    @GetMapping(value = ["/stocks/{symbol}"],
                produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
    fun prices(@PathVariable symbol: String): Flux&lt;StockPrice&gt; {
        return Flux
                .interval(Duration.ofSeconds(1))
                .map { StockPrice(symbol, randomStockPrice(), LocalDateTime.now()) }
    }

    private fun randomStockPrice(): Double {
        return ThreadLocalRandom.current().nextDouble(100.0)
    }
}


Running the Application

Run the application to see it start up correctly. Open up a web browser and navigate to http://localhost:8080/stocks/DEMO, you should see the events tick once a second, and see the stock price represented as a JSON string:

data:{"symbol":"DEMO","price":89.06318870033823,"time":"2019-10-17T17:00:25.506109"}


Summary

We've created a simple Kotlin Spring Boot application that uses Reactive Streams to emit a randomly generated stock price once a second.

@SpringBootApplication
class StockServiceApplication

fun main(args: Array<String>) {
    runApplication<StockServiceApplication>(*args)
}

@RestController
class RestController() {
    @GetMapping(value = ["/stocks/{symbol}"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
    fun prices(@PathVariable symbol: String): Flux<StockPrice> {
        return Flux.interval(Duration.ofSeconds(1))
                   .map { StockPrice(symbol, randomStockPrice(), LocalDateTime.now()) }
    }

    private fun randomStockPrice(): Double {
        return ThreadLocalRandom.current().nextDouble(100.0)
    }
}

data class StockPrice(val symbol: String, val price: Double, val time: LocalDateTime)


In the rest of the tutorial, we'll show how to connect to this server to retrieve prices, and how to create a chart that shows the price updates in real-time. Stay tuned!

Full code is available on GitHub.

Further Reading

Fully Reactive: Spring, Kotlin, and JavaFX Playing Together [Links]

Kotlin Microservice With Spring Boot Tutorial

Spring Reactive Programming in Java

Spring Framework Spring Boot REST Web Protocols Kotlin (programming language) intellij Web Service microservice

Published at DZone with permission of Trisha Gee, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Getting Started With Istio in AWS EKS for Multicluster Setup
  • Top 10 Engineering KPIs Technical Leaders Should Know
  • Event-Driven Architecture Using Serverless Technologies
  • Integrating AWS With Salesforce Using Terraform

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: