Kotlin Microservices With Micronaut, Spring Cloud, and JPA

Kotlin Microservices With Micronaut, Spring Cloud, and JPA

In this article, we'll learn how to create microservice applications written in Kotlin, using the Micronaut framework, Spring Cloud, and JPA for a little extra help.

In this article, we'll learn how to create microservice applications written in Kotlin, using the Micronaut framework, Spring Cloud, and JPA for a little extra help.

The Micronaut Framework provides support for Kotlin built upon the Kapt compiler plugin. It also implements the most popular cloud-native patterns, like distributed configuration, service discovery, and client-side load balancing. These features allow you to include an application that’s been built on top of Micronaut into an existing microservices-based system. The most popular example of such an approach may be integration with the Spring Cloud ecosystem. If you have already used Spring Cloud, it is very likely you built your microservices-based architecture using the Eureka discovery server and Spring Cloud Config as a configuration server. Beginning with version 1.1, Micronaut supports both these popular tools as part of the Spring Cloud project. That’s good news because, in version 1.0, the only supported distributed solution was Consul, and there was no way to use Eureka discovery together with Consul’s property source (running them together ends with an exception).

In this article, you will learn how to:

  • configure Micronaut Maven support for Kotlin using the Kapt compiler.
  • implement microservices with Micronaut and Kotlin.
  • integrate Micronaut with the Spring Cloud Eureka discovery server.
  • integrate Micronaut with the Spring Cloud Config server.
  • configure JPA/Hibernate support for an application built on top Micronaut.
  • run a single instance of PostgreSQL shared between all sample microservices.

We also have three microservices that communicate with each other. We use Spring Cloud Eureka and Spring Cloud Config for discovery and distributed configuration instead of Consul. Every service has a back-end store — PostgreSQL database. This architecture has been visualized in the following picture.

After that short introduction, we may proceed to the development. Let’s begin from configuring Kotlin support for Micronaut.

1. Kotlin With Micronaut — Configuration

Support for Kotlin with the Kapt compiler plugin is described well on the Micronaut docs site. However, I decided to use Maven instead of Gradle, so our configuration will be slightly different than instructions for Gradle. We configure Kapt inside the Maven plugin for Kotlin, kotlin-maven-plugin. Thanks to that Kapt, we will create Java “stub” classes for each of our Kotlin classes, which can then be processed by Micronaut’s Java annotation processor. The Micronaut annotation processors are declared inside the tag annotationProcessorPaths, in the configuration section. Here’s the full Maven configuration to provide support for Kotlin. Beside the core library micronaut-inject-java, we also use annotations from tracing, OpenAPI, and JPA libraries.

<plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-allopen</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>
    <configuration>
        <jvmTarget>1.8</jvmTarget>
    </configuration>
    <executions>
        <execution>
            <id>compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>test-compile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>test-compile</goal>
            </goals>
        </execution>
        <execution>
            <id>kapt</id>
            <goals>
                <goal>kapt</goal>
            </goals>
            <configuration>
                <sourceDirs>
                    <sourceDir>src/main/kotlin</sourceDir>
                </sourceDirs>
                <annotationProcessorPaths>
                    <annotationProcessorPath>
                        <groupId>io.micronaut</groupId>
                        <artifactId>micronaut-inject-java</artifactId>
                        <version>${micronaut.version}</version>
                    </annotationProcessorPath>
                    <annotationProcessorPath>
                        <groupId>io.micronaut.configuration</groupId>
                        <artifactId>micronaut-openapi</artifactId>
                        <version>${micronaut.version}</version>
                    </annotationProcessorPath>
                    <annotationProcessorPath>
                        <groupId>io.micronaut</groupId>
                        <artifactId>micronaut-tracing</artifactId>
                        <version>${micronaut.version}</version>
                    </annotationProcessorPath>
                    <annotationProcessorPath>
                        <groupId>javax.persistence</groupId>
                        <artifactId>javax.persistence-api</artifactId>
                        <version>2.2</version>
                    </annotationProcessorPath>
                    <annotationProcessorPath>
                        <groupId>io.micronaut.configuration</groupId>
                        <artifactId>micronaut-hibernate-jpa</artifactId>
                        <version>1.1.0.RC2</version>
                    </annotationProcessorPath>
                </annotationProcessorPaths>
            </configuration>
        </execution>
    </executions>
</plugin>

We also should not run maven-compiler-plugin during the compilation phase. The Kapt compiler generates Java classes, so we don’t need to run any other compilators during the build.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <proc>none</proc>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
    <executions>
        <execution>
            <id>default-compile</id>
            <phase>none</phase>
        </execution>
        <execution>
            <id>default-testCompile</id>
            <phase>none</phase>
        </execution>
        <execution>
            <id>java-compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>java-test-compile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Finally, we will add the Kotlin core library and Jackson module for JSON serialization.

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
    <version>${kotlin.version}</version>
</dependency>

If you are running the application with IntelliJ, you should first enable annotation processing. To do that, go to Build, Execution, Deployment -> Compiler -> Annotation Processors as shown below.

2. Running Postgres

Before proceeding to the development phase, we have to start an instance of the PostgreSQL database. It will be started as a Docker container. For me, PostgreSQL is now available under the address,192.168.99.100:5432, because I’m using Docker Toolbox.

$ docker run -d --name postgres -e POSTGRES_USER=micronaut -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=micronaut -p 5432:5432 postgres

3. Enabling Hibernate for Micronaut

Hibernate configuration is a little harder for Micronaut than for Spring Boot. We don’t have any projects like Spring Data JPA, where almost everything is auto-configured. Beside specific JDBC drivers for integration with a database, we have to include the following dependencies. We may choose between three available libraries that provide data source implementation: Tomcat, Hikari, or DBCP.

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.5</version>
</dependency>
<dependency>
    <groupId>io.micronaut.configuration</groupId>
    <artifactId>micronaut-jdbc-hikari</artifactId>
</dependency>
<dependency>
    <groupId>io.micronaut.configuration</groupId>
    <artifactId>micronaut-hibernate-jpa</artifactId>
</dependency>
<dependency>
    <groupId>io.micronaut.configuration</groupId>
    <artifactId>micronaut-hibernate-validator</artifactId>
</dependency>

The next step is to provide some configuration settings. All the properties will be stored on the configuration server. We have to set the database connection settings and credentials. The JPA configuration settings are provided under the jpa.* key. We force Hibernate to update the database on application startup and print all the SQL logs (only for tests).

datasources:
  default:
    url: jdbc:postgresql://192.168.99.100:5432/micronaut?ssl=false
    username: micronaut
    password: 123456
    driverClassName: org.postgresql.Driver
jpa:
  default:
    packages-to-scan:
      - 'pl.piomin.services.department.model'
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        show_sql: true

Here’s our sample domain object.

@Entity
data class Department(@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "department_id_seq") @SequenceGenerator(name = "department_id_seq", sequenceName = "department_id_seq") var id: Long,
                      var organizationId: Long, var name: String) {

    @Transient
    var employees: MutableList<Employee> = mutableListOf()

}

The repository bean needs to inject EntityManager using the @PersistentContext and @CurrentSession annotations. All functions need to be annotated with @Transactional, which does not require the methods to be final (open modifier in Kotlin).

@Singleton
open class DepartmentRepository(@param:CurrentSession @field:PersistenceContext val entityManager: EntityManager) {

    @Transactional
    open fun add(department: Department): Department {
        entityManager.persist(department)
        return department
    }

    @Transactional(readOnly = true)
    open fun findById(id: Long): Department = entityManager.find(Department::class.java, id)

    @Transactional(readOnly = true)
    open fun findAll(): List<Department> = entityManager.createQuery("SELECT d FROM Department d").resultList as List<Department>

    @Transactional(readOnly = true)
    open fun findByOrganization(organizationId: Long) = entityManager.createQuery("SELECT d FROM Department d WHERE d.organizationId = :orgId")
            .setParameter("orgId", organizationId)
            .resultList as List<Department>

}

4. Running Spring Cloud Config Server

Running the Spring Cloud Config server is very simple. I have already described that in some of my previous articles. All those were prepared for Java, while today we start it as Kotlin application. Here’s our main class. It should be annotated with @EnableConfigServer.

@SpringBootApplication
@EnableConfigServer
class ConfigApplication

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

Besides the Kotlin core dependency, we need to include the artifact, spring-cloud-config-server.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
    <version>${kotlin.version}</version>
</dependency>

By default, the config server tries to use Git as a properties source backend. We prefer using classpath resources, which is much simpler for our tests. To do that, we have to enable the native profile. We will also set the server port to 8888.

spring:
  application:
    name: config-service
  profiles:
    active: native
server:
  port: 8888

If you place all the configurations under the directory /src/main/resources/config, they will be loaded automatically after the app starts up.

Here’s the configuration file for department-service.

micronaut:
  server:
    port: -1
  router:
    static-resources:
      swagger:
        paths: classpath:META-INF/swagger
        mapping: /swagger/**
datasources:
  default:
    url: jdbc:postgresql://192.168.99.100:5432/micronaut?ssl=false
    username: micronaut
    password: 123456
    driverClassName: org.postgresql.Driver
jpa:
  default:
    packages-to-scan:
      - 'pl.piomin.services.department.model'
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        show_sql: true
endpoints:
  info:
    enabled: true
    sensitive: false
eureka:
  client:
    registration:
      enabled: true
    defaultZone: "localhost:8761"

5. Running a Eureka Server

The Eureka server will also be run as a Spring Boot application written in Kotlin.

@SpringBootApplication
@EnableEurekaServer
class DiscoveryApplication

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

We also need to include a single dependency, spring-cloud-starter-netflix-eureka-server, beside kotlin-stdlib-jdk8.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
    <version>${kotlin.version}</version>
</dependency>

We run a standalone instance of Eureka on port 8761.

spring:
  application:
    name: discovery-service
server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

6. Integrating Micronaut With Spring Cloud

The implementation of a distributed configuration client is automatically included in Micronaut’s core. We only need to include the module for service discovery.

<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-discovery-client</artifactId>
</dependency>

We don’t have to place anything in the source code. All the features can be enabled via configuration settings. First, we need to enable the config client by setting the micronaut.config-client.enabled property to true. The next step is to enable specific implementations of the config client — in our case, Spring Cloud Config — and then set the target URL.

micronaut:
  application:
    name: department-service
  config-client:
    enabled: true
spring:
  cloud:
    config:
      enabled: true
      uri: http://localhost:8888/

Each application fetches the properties frthe om configuration server. The part of the configuration responsible for enabling discovery based on the Eureka server is visible below.

eureka:
  client:
    registration:
      enabled: true
    defaultZone: "localhost:8761"

7. Running Applications

Kapt needs to be able to compile Kotlin code to Java succesfully. That’s why we place a method inside the class declaration, and annotate it with @JvmStatic. The main class visible below is also annotated with @OpenAPIDefinition in order to generate a Swagger definition for API methods.

@OpenAPIDefinition(
        info = Info(
                title = "Departments Management",
                version = "1.0",
                description = "Department API",
                contact = Contact(url = "https://piotrminkowski.wordpress.com", name = "Piotr Mińkowski", email = "[email protected]")
        )
)
open class DepartmentApplication {

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            Micronaut.run(DepartmentApplication::class.java)
        }
    }

}

Here’s the controller class from department-service. It injects a repository bean for database integration and EmployeeClient for HTTP communication with employee-service.

@Controller("/departments")
open class DepartmentController(private val logger: Logger = LoggerFactory.getLogger(DepartmentController::class.java)) {

    @Inject
    lateinit var repository: DepartmentRepository
    @Inject
    lateinit var employeeClient: EmployeeClient

    @Post
    fun add(@Body department: Department): Department {
        logger.info("Department add: {}", department)
        return repository.add(department)
    }

    @Get("/{id}")
    fun findById(id: Long): Department? {
        logger.info("Department find: id={}", id)
        return repository.findById(id)
    }

    @Get
    fun findAll(): List<Department> {
        logger.info("Department find")
        return repository.findAll()
    }

    @Get("/organization/{organizationId}")
    @ContinueSpan
    open fun findByOrganization(@SpanTag("organizationId") organizationId: Long): List<Department> {
        logger.info("Department find: organizationId={}", organizationId)
        return repository.findByOrganization(organizationId)
    }

    @Get("/organization/{organizationId}/with-employees")
    @ContinueSpan
    open fun findByOrganizationWithEmployees(@SpanTag("organizationId") organizationId: Long): List<Department> {
        logger.info("Department find: organizationId={}", organizationId)
        val departments = repository.findByOrganization(organizationId)
        departments.forEach { it.employees = employeeClient.findByDepartment(it.id) }
        return departments
    }

}

It is worth taking a look at the HTTP client implementation. It has been discussed in the details in my last article about Micronaut, A Quick Guide to Microservices with the Micronaut Framework.

@Client(id = "employee-service", path = "/employees")
interface EmployeeClient {

@Get("/department/{departmentId}")
fun findByDepartment(departmentId: Long): MutableList<Employee>

}

You can run all the microservices using IntelliJ. You may also build the whole project with Maven using themvn clean install command, and then run them using the java -jar command. Thanks to maven-shade-plugin, our applications will be generated as uber jars. We then can run them in the following order: config-service, discovery-service, and microservices.

$ java -jar config-service/target/config-service-1.0-SNAPSHOT.jar
$ java -jar discovery-service/target/discovery-service-1.0-SNAPSHOT.jar
$ java -jar employee-service/target/employee-service-1.0-SNAPSHOT.jar
$ java -jar department-service/target/department-service-1.0-SNAPSHOT.jar
$ java -jar organization-service/target/organization-service-1.0-SNAPSHOT.jar

After this, you may take a look at the Eureka dashboard available under the address http://localhost:8761 in order to see a list of the running services. You may also perform some tests by running HTTP API methods.

Summary

The sample application’s source code is available on GitHub in the repository sample-micronaut-microservices in the Kotlin branch. You can refer to that repository for more implementation details that have not been included in this article.

Build Spring Boot Apps using the Kotlin Programming

Build Spring Boot Apps using the Kotlin Programming

In this tutorial, you will build a Spring Boot application from scratch, using Kotlin as the main language. You will learn how Kotlin works with Spring and how to integrate the code with other Java libraries.

Java, once considered the coolest kid on the block, is now seen by many as a legacy language. Some developers believe it stopped evolving when it comes to features and many consider it too verbose, claiming it makes code hard to read.

JetBrains, the company behind IntelliJ decided to do something about it and create a modern language that would run inside the Java Virtual Machine. This project became Kotlin, a quickly growing and popular language.

Google then announced official support for Kotlin on Android, further accelerating its adoption. Many companies started to replace Java with Kotlin as their main language to take advantage of the new features it provides. Kotlin is now an increasingly important language for developers inside the JVM ecosystem to know and understand.

In this tutorial, you will build a Spring Boot application from scratch, using Kotlin as the main language. You will learn how Kotlin works with Spring and how to integrate the code with other Java libraries. By the end, you will have a secure Spring application running in Kotlin that authenticates users via OAuth 2.0.

Create the Kotlin Application with Spring Initializr

Let’s start by creating the project using Spring Initializr.

Go to the Spring Initializr website and type in the following information:

  • Project: Gradle Project
  • Language: Kotlin
  • Group: com.okta
  • Artifact: spring-kotlin
  • Options:
  • Package Name: com.okta
  • Dependencies: Spring Web

You can also use the command line to get the same result:

curl https://start.spring.io/starter.zip \
       -d language=kotlin \
       -d style=web \
       -d packageName=com.okta \
       -d name=spring-kotlin \
       -d type=gradle-project \
       -o spring-kotlin.zip

You can choose to use either Maven or Gradle. Since Gradle is the most common build tool to go along with Kotlin, this tutorial will go for it.

Import the project into your favorite IDE. Although you can choose your favorite, I strongly recommend IntelliJ, from the creators of Kotlin.

If you use IntelliJ, you don’t need to download Kotlin since it ships included with the IDE. Otherwise download the latest release.

Once you’ve imported the project, it will have a single file named SpringKotlinApplication.kt. Inside the file, you will find the following code:

@SpringBootApplication
class SpringKotlinApplication

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

This file contains the main function, which bootstraps the application. To declare a function in Kotlin you use the keyword fun, followed by its name, the parameters, and the return type. When there is no return type, you don’t specify anything, which is the case with this function.

Here you also have a class annotated with SpringBootApplication that will behave the same way as in Java. You may also notice that SpringKotlinApplication is not declared as public. The reason is pretty simple: all classes are public in Kotlin by default!

Next, create a REST endpoint. As with Java, you need to create a class and annotate it with RestController.

Inside src/com/okta/controller/, create the class GreetController with the following code:

package com.okta.controller

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class GreetController {

   @GetMapping("/greet")
   fun greet(): String {
       return "Hello, World"
   }
}

As with classes, all functions are public by default so there is no need to add an explicit modifier. The other big difference is the function declaration: the return type goes after the name of the method, separated by a colon.

That’s it! You have created your first application in Spring using Kotlin.

Run the application by executing the class SpringKotlinApplication in your IDE (or with ./gradlew bootRun). After that, go to http://localhost:8080/greet and you should see the following greeting message in your browser:

Hello, World!
Make the Kotlin Application Endpoint Dynamic

You can make the message in your endpoint available to greet any person. Let’s update it to receive a name as the input and display a personalized greeting message:

Inside the GreetController file, make the following changes:

@GetMapping("/greet")
fun greet(@RequestParam("name") name: String): String {
   return "Hello, $name!"
}

The greet function now receives a parameter called name. In Kotlin, you declare parameters by specifying the name first, followed by a colon and its type. This is the same convention used to declare a function. The RequestParam annotation is placed in the same position as you would in Java code.

You might also have noticed that you didn’t have to concatenate Strings to display the input value. Kotlin has a built-in feature called String templates, which allows you to reference a variable by putting the $ sign, followed by the variable name itself.

Run the application again and open http://localhost:8080/greet?name=john. You should see the message below:

Hello, john!

Great! With very little effort, your application can greet any user by name from now on.

Extensions: Say Farewell to Utility Classes

Your endpoint is working, but there is little problem with the current version: the user might input their name in all lowercase characters.

To fix this, you can capitalize the first character of the name before returning it. In Java, you usually achieve this by creating or importing a utility class that you then call to do the action. For instance, you could import StringUtils from Apache Commons to your project and add the following code:

String capitalizedName = StringUtils.capitalize(name);
return "Hello, " + capitalizedName + "!";

In Kotlin, you don’t need to use a utility class. Instead, use a feature called extension functions. This feature allows you to add functions to existing classes, even when they are final or outside your project scope. All you have to do is inform the class you want to extend with the method to make it available:

fun String.capitalize(): String {
   if (this.isEmpty()) {
       return this
   } else if (this.length == 1) {
       return this.toUpperCase()
   } else {
       return this[0].toTitleCase() + this.substring(1).toLowerCase()
   }
}

The function above ensures the first letter of the word is in uppercase and all others are in lowercase.

The extension function is declared in the same way as a regular function. The only difference is you have to specify the class you want to extend before the name of the method. In our case, you want to add a capitalize function in the String class, which means you need to declare the function as String.capitalize.

Go to the greet function and make the following changes:

@GetMapping("/")
fun greet(@RequestParam("name") name: String): String {
   val capitalizedName = name.capitalize()
   return "Hello $capitalizedName!"
}

Although you declared the function in your project, you make the call as it was defined inside the String class! This eliminates the need to create utility classes and concentrates the methods in one place, making it easier to find the function you want to use.

Restart the application and reload http://localhost:8080/greet?name=john you should see the following message:

Hello, John!

There you go! Now your application displays the name with a capitalized first letter :-)

When: An Enhanced Switch Operator

Take a closer look at the capitalize method you created earlier and note that all three if statements are related. This is a common programming pattern the creators of Kotlin decided to handle with a new keyword: when.

You can think of the when as an enhanced switch statement. In Java, you can verify if an enum is of a particular type by using switch:

switch(myEnum) {
   case ENUM_A:
       // code here
   case ENUM_B:
       // code here
   default:
   // code here
}

This is very useful to make cleaner code, but it’s also limited because it can only verify the type of the variable. In Kotlin, when lets you verify any condition. That way you get cleaner code while performing more advanced operations.

Let’s rewrite the previous capitalize method using when.

fun String.capitalize(): String {
   when (this.length) {
       0 -> return this
       1 -> return this.toUpperCase()
       else -> return this[0].toTitleCase() + this.substring(1).toLowerCase()
   }
}

In this new version, you verify the length of the current String and return the result based on its length.

But the power of when doesn’t end there. You can even mix up different types of conditionals in the same clause. For instance, you could write the above method like this:

fun String.capitalize(): String {
   when {
       this.isEmpty() -> return this
       this.length == 1 -> return this.toUpperCase()
       else -> return this[0].toTitleCase() + this.substring(1).toLowerCase()
   }
}

As you can see, one of the conditionals calls isEmpty(), while the other one verifies the length of the String. As long as your expression can be evaluated as a boolean value, you can use it inside of a when expression.

Leverage Java Libraries In Your Kotlin App

Although your application is still very simple, you can make it look like a professional app with just a few small tweaks. For instance, greet the logged-in user by name instead of asking for it as a parameter every time.To make that work of course, you need to implement user authentication first.

Authentication is a vital part of any modern app, but can you incorporate auth into your project without layers of configuration and code? The answer is yes! We’ll use OAuth 2.0 to authenticate users and display a greeting message based on the user’s name with no headache.

Recall how Kotlin can use libraries from the Java ecosystem? Add Okta’s Java library written to handle the OAuth 2.0 flow inside your application.

To start, open the build.gradle.kts file. Inside the dependencies tag, add the following line:

implementation("com.okta.spring:okta-spring-boot-starter:1.2.1")

Your dependencies object should look like this:

dependencies {
   implementation("org.springframework.boot:spring-boot-starter-web")
   implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
   implementation("org.jetbrains.kotlin:kotlin-reflect")
   implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
   implementation("com.okta.spring:okta-spring-boot-starter:1.2.1")
   testImplementation("org.springframework.boot:spring-boot-starter-test")
}

This dependency adds both Okta and Spring Security to your project. They make it simple to ensure only authenticated users can access protected areas of your application.

If you don’t have an Okta account, go ahead and create a free one. After registering, go through the following steps:

  • Log into your account
  • Click Applications
  • Click on Add Application. You will be redirected to the following page:

Now that you have your Okta application, you can use it to authenticate users in your Kotlin app.

Add the following environment variables to your application:

OKTA_OAUTH2_ISSUER=https://{yourOktaDomain}/oauth2/default
OKTA_OAUTH2_CLIENT_ID={CLIENT_ID}
OKTA_OAUTH2_CLIENT_SECRET={CLIENT_SECRET}

You will find {CLIENT_ID} and {CLIENT_SECRET} on the application page in Okta’s dashboard. To find it, follow the steps below:

  • In your Okta Admin Console’s menu, go to Applications
  • Select the “hello-world” application
  • Click on the General tab

You should see both values inside the Client Credentials area.

Your {yourOktaDomain} will be visible in your Okta dashboard, just click on Dashboard in the menu. You will see the Org URL in the right upper corner.

The last step is to modify your greet endpoint to pull the name from the authenticated user. Go to the GreetController class and apply the following changes:

package com.okta.controller

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal
import org.springframework.security.oauth2.core.oidc.user.OidcUser

@RestController
class GreetController {

   @GetMapping("/greet")
   fun greet(@AuthenticationPrincipal user: OidcUser): String {
       val capitalizedName = user.givenName.capitalize()
       return "Hello, $capitalizedName!"
   }

   fun String.capitalize(): String {
       when {
           this.isEmpty() -> return this
           this.length == 1 -> return this.toUpperCase()
           else -> return this[0].toTitleCase() + this.substring(1).toLowerCase()
       }
   }
}

The main difference here is that you are not receiving the user as a parameter anymore. Since you annotated the function with AuthenticationPrincipal, Spring knows that you want to retrieve the current user and will do it automatically.

That’s it! You now have an application with secure authentication out of the box. Go to http://localhost:8080/greet. and you should be redirected to the Okta’s login page:

Once the user enters their username and password they’ll be redirected to your greeting page again. In my case, I see the following:

 Hello, Daniel!

Congratulations! You just finished your first app written in Kotlin. You also took advantage of the JVM ecosystem by adding authentication in a simple, secure way. Take a look at the final code on GitHub.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

☞ Angular 7 + Spring Boot CRUD Example

☞ Angular 8 + Spring Boot 2.2: Build a CRUD App Today! 

☞ Top 5 Kotlin Features That Every Android App Developer Must Know

☞ Java Vs. Kotlin: Which One Will Be the Best in 2019?



Originally published by Daniel Pereira at https://developer.okta.com

ECommerce Mobile App Development | Ecommerce Mobile App Development Services

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates. **Know about [Top ECommerce Mobile App Development...

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates.

Know about Top ECommerce Mobile App Development Company

How to migrate From Spring Boot Apps to Functional Kotlin

How to migrate From Spring Boot Apps to Functional Kotlin

Migrating Spring Boot Apps from Annotation-based Config to Functional with Kotlin

In the latest years, there has been some push-back against frameworks, and more specifically annotations: some call them magic. Obviously, they make understanding the flow of the application harder. Spring and Spring Boot latest versions go along this trend, by offering an additional way to configure beans with explicit code instead of annotations. It's declarative in the sense it looks like configuration, though it's based on Domain-Specific Language(s). This talk aims to demo a step-by-step process to achieve that.

What will the audience learn from this talk?

  •   How to migrate from controllers to routes
  •   How to migrate from annotations to declarative ("functional")
  •   New Kotlin DSLs for routes & beans declaration
  •   The future!

Does it feature code examples and/or live coding?

Yes, my talk is based on the migration of a demo app. I have a reference in my last slides that point to the Github repo, so that people can study it at home afterwards.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Angular 7 + Spring Boot CRUD Example

Angular 8 + Spring Boot 2.2: Build a CRUD App Today! 

Kotlin Microservices With Micronaut, Spring Cloud, and JPA