---
tags: [kotlin,rest,data,jpa]
projects: [spring-data-jpa,spring-framework,spring-boot]
---
:toc:
:icons: font
:source-highlighter: prettify
:project_id: spring-boot
:tabsize: 2

This tutorial shows you how to build efficiently a sample blog application by combining the power of https://projects.spring.io/spring-boot/[Spring Boot] and http://kotlinlang.org/[Kotlin].

If you are starting with Kotlin, you can learn the language by reading the https://kotlinlang.org/docs/reference/[reference documentation] and following the online https://try.kotlinlang.org[Kotlin Koans tutorial].

Spring Kotlin support is documented in the https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#kotlin[Spring Framework] and https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-kotlin.html[Spring Boot] reference documentation. If you need help, search or ask questions with the https://stackoverflow.com/questions/tagged/kotlin+spring[`spring` and `kotlin` tags on StackOverflow] or come discuss in the `#spring` channel of http://slack.kotlinlang.org/[Kotlin Slack].

== Creating a New Project

First we need to create a Spring Boot application, which can be done in a number of ways.

[[using-the-initializr-website]]
=== Using the Initializr Website

Visit https://start.spring.io and choose the Kotlin language. Or visit https://start.spring.io/#!language=kotlin to preselect Kotlin.

	. let the default "Maven Project" or select "Gradle Project" depending on which build topl you want to use
	. Click "Switch to the full version" and enter the following artifact coordinates:
		- **Artifact:** `blog`
		- **Package Name:** `blog`
	. Add the following dependencies:
		- Web
		- Mustache
		- JPA
		- H2
	. Click "Generate Project".

image::./images/initializr.png[]

The .zip file contains a standard project in the root directory, so you might want to create an empty directory before you unpack it.

[[using-command-line]]
=== Using command line

You can use the Initializr HTTP API https://docs.spring.io/initializr/docs/current/reference/htmlsingle/#command-line[from the command line] with, for example, curl on a UN*X like system:

[source]
----
$ mkdir blog && cd blog
$ curl https://start.spring.io/starter.zip -d language=kotlin -d style=web,mustache,jpa,h2 -d packageName=blog -d name=Blog -o blog.zip
----

Add `-d type=gradle-project` if you want to use Maven.

[[using-intellij-idea]]
=== Using IntelliJ IDEA

Spring Initializr is also integrated in IntelliJ IDEA Ultimate edition and allows you to create and import a new project without having to leave the IDE for the command-line or the web UI.

To access the wizard, go to File | New | Project, and select Spring Initializr.

Follow the steps of the wizard to use the following parameters:

 - Package name: "blog"
 - Artifact: "blog"
 - Type: Maven project or Gradle Project
 - Language: Kotlin
 - Name: "Blog"
 - Dependencies: "Web", "Mustache", JPA" and "H2"

[[reveal-gradle]]
[.reveal-gradle]
== Gradle Build

[[use-gradle]]
[.use-gradle]
== Gradle Build

=== Plugins

In addition to the obvious https://kotlinlang.org/docs/reference/using-gradle.html[Kotlin Gradle plugin], the default configuration declares the https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support[kotlin-spring plugin] which automatically opens classes and methods (unlike in Java, the default qualifier is `final` in Kotlin) annotated or meta-annotated with Spring annotations. This is useful to be able to create `@Configuration` or `@Transactional` beans without having to add the `open` qualifier required by CGLIB proxies for example.

In order to be able to use Kotlin non-nullable properties with JPA, https://kotlinlang.org/docs/reference/compiler-plugins.html#jpa-support[Kotlin JPA plugin] is also enabled. It generates no-arg constructors for any class annotated with `@Entity`, `@MappedSuperclass` or `@Embeddable`.


`build.gradle`
[source,groovy]
----
plugins {
	id 'org.jetbrains.kotlin.plugin.jpa' version '1.2.71'
	id 'org.springframework.boot' version '2.1.3.RELEASE'
	id 'org.jetbrains.kotlin.jvm' version '1.2.71'
	id 'org.jetbrains.kotlin.plugin.spring' version '1.2.71'
}

apply plugin: 'kotlin-jpa'
apply plugin: 'io.spring.dependency-management'
----

=== Compiler options

One of Kotlin's key features is https://kotlinlang.org/docs/reference/null-safety.html[null-safety] - which cleanly deals with `null` values at compile time rather than bumping into the famous `NullPointerException` at runtime. This makes applications safer through nullability declarations and expressing "value or no value" semantics without paying the cost of wrappers like `Optional`. Note that Kotlin allows using functional constructs with nullable values; check out this http://www.baeldung.com/kotlin-null-safety[comprehensive guide to Kotlin null-safety].

Although Java does not allow one to express null-safety in its type-system, Spring Framework provides null-safety of the whole Spring Framework API via tooling-friendly annotations declared in the `org.springframework.lang` package. By default, types from Java APIs used in Kotlin are recognized as https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types[platform types] for which null-checks are relaxed. https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support[Kotlin support for JSR 305 annotations] + Spring nullability annotations provide null-safety for the whole Spring Framework API to Kotlin developers, with the advantage of dealing with `null` related issues at compile time.

This feature can be enabled by adding the `-Xjsr305` compiler flag with the `strict` options.

Notice also that Kotlin compiler is configured to generate Java 8 bytecode (Java 6 by default).

`build.gradle`
[source,groovy]
----
sourceCompatibility = 1.8
compileKotlin {
	kotlinOptions {
		freeCompilerArgs = ["-Xjsr305=strict"]
		jvmTarget = "1.8"
	}
}
compileTestKotlin {
	kotlinOptions {
		freeCompilerArgs = ["-Xjsr305=strict"]
		jvmTarget = "1.8"
	}
}
----

=== Dependencies

3 Kotlin specific libraries are required for such Spring Boot web application and configured by default:

 - `kotlin-stdlib-jdk8` is the Java 8 variant of Kotlin standard library
 - `kotlin-reflect` is Kotlin reflection library
 - `jackson-module-kotlin` adds support for serialization/deserialization of Kotlin classes and data classes (single constructor classes can be used automatically, and those with secondary constructors or static factories are also supported)

`build.gradle`
[source,groovy]
----
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-mustache'
	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'
	runtimeOnly 'com.h2database:h2'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
----

Spring Boot Gradle plugin automatically uses the Kotlin version declared via the Kotlin Gradle plugin.

[[reveal-maven]]
[.reveal-maven]
== Maven Build

[[use-gradle]]
[.use-gradle]
== Maven Build

=== Plugins

In addition to the obvious https://kotlinlang.org/docs/reference/using-maven.html[Kotlin Maven plugin], the default configuration declares the https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support[kotlin-spring plugin] which automatically opens classes and methods (unlike in Java, the default qualifier is `final` in Kotlin) annotated or meta-annotated with Spring annotations. This is useful to be able to create `@Configuration` or `@Transactional` beans without having to add the `open` qualifier required by CGLIB proxies for example.

In order to be able to use Kotlin non-nullable properties with JPA, https://kotlinlang.org/docs/reference/compiler-plugins.html#jpa-support[Kotlin JPA plugin] is also enabled. It generates no-arg constructors for any class annotated with `@Entity`, `@MappedSuperclass` or `@Embeddable`.

`pom.xml`
[source,xml]
----
<build>
		<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
		<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.jetbrains.kotlin</groupId>
				<artifactId>kotlin-maven-noarg</artifactId>
				<version>${kotlin.version}</version>
				<configuration>
					<compilerPlugins>
						<plugin>jpa</plugin>
					</compilerPlugins>
				</configuration>
			</plugin>
			<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>
----

One of Kotlin's key features is https://kotlinlang.org/docs/reference/null-safety.html[null-safety] - which cleanly deals with `null` values at compile time rather than bumping into the famous `NullPointerException` at runtime. This makes applications safer through nullability declarations and expressing "value or no value" semantics without paying the cost of wrappers like `Optional`. Note that Kotlin allows using functional constructs with nullable values; check out this http://www.baeldung.com/kotlin-null-safety[comprehensive guide to Kotlin null-safety].

Although Java does not allow one to express null-safety in its type-system, Spring Framework provides null-safety of the whole Spring Framework API via tooling-friendly annotations declared in the `org.springframework.lang` package. By default, types from Java APIs used in Kotlin are recognized as https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types[platform types] for which null-checks are relaxed. https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support[Kotlin support for JSR 305 annotations] + Spring nullability annotations provide null-safety for the whole Spring Framework API to Kotlin developers, with the advantage of dealing with `null` related issues at compile time.

This feature can be enabled by adding the `-Xjsr305` compiler flag with the `strict` options.

Notice also that Kotlin compiler is configured to generate Java 8 bytecode (Java 6 by default).

=== Dependencies

3 Kotlin specific libraries are required for such Spring Boot web application and configured by default:

 - `kotlin-stdlib-jdk8` is the Java 8 variant of Kotlin standard library
 - `kotlin-reflect` is Kotlin reflection library (mandatory as of Spring Framework 5)
 - `jackson-module-kotlin` adds support for serialization/deserialization of Kotlin classes and data classes (single constructor classes can be used automatically, and those with secondary constructors or static factories are also supported)

`pom.xml`
[source,xml]
----
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-mustache</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</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>

	<dependency>
		<groupId>com.h2database</groupId>
		<artifactId>h2</artifactId>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>
----

=== Understanding the generated Application

`src/main/kotlin/blog/BlogApplication.kt`
[source,kotlin]
----
package blog

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

@SpringBootApplication
class BlogApplication

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

Compared to Java, you can notice the lack of semicolons, the lack of brackets on empty class (you can add some if you need to declare beans via `@Bean` annotation) and the use of `runApplication` top level function. `runApplication<BlogApplication>(*args)` is Kotlin idiomatic alternative to `SpringApplication.run(BlogApplication::class.java, *args)` and can be used to customize the application with following syntax.

`src/main/kotlin/blog/BlogApplication.kt`
[source,kotlin]
----
fun main(args: Array<String>) {
	runApplication<BlogApplication>(*args) {
		setBannerMode(Banner.Mode.OFF)
	}
}
----

== Writing your first Kotlin controller

Let's create a simple controller to display a simple web page.

`src/main/kotlin/blog/HtmlController.kt`
[source,kotlin]
----
package blog

import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.ui.set
import org.springframework.web.bind.annotation.GetMapping

@Controller
class HtmlController {

	@GetMapping("/")
	fun blog(model: Model): String {
		model["title"] = "Blog"
		return "blog"
	}

}
----

Notice that we are using here a https://kotlinlang.org/docs/reference/extensions.html[Kotlin extension] that allows to add Kotlin functions or operators to existing Spring types. Here we import the `org.springframework.ui.set` extension function in order to be able to write `model["title"] = "Blog"` instead of `model.addAttribute("title", "Blog")`.
The https://docs.spring.io/spring-framework/docs/current/kdoc-api/spring-framework/[Spring Framework KDoc API] lists all the Kotlin extensions provided to enrich the Java API.

We also need to create the associated Mustache templates.

`src/main/resources/templates/header.mustache`
[source]
----
<html>
<head>
	<title>{{title}}</title>
</head>
<body>
----

`src/main/resources/templates/footer.mustache`
[source]
----
</body>
</html>
----

`src/main/resources/templates/blog.mustache`
[source]
----
{{> header}}

<h1>{{title}}</h1>

{{> footer}}
----

Start the web application by running the `main` function of `BlogApplication.kt`, and go to `http://localhost:8080/`, you should see a sober web page with a "Blog" headline. 

== Testing with JUnit 5

While JUnit 4 is still the default testing framework provided with Spring Boot, JUnit 5 provides various features very handy with Kotlin, including https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-junit-jupiter-di[autowiring of contructor/method parameters] which allows to use non-nullable `val` properties and the possibility to use `@BeforeAll`/`@AfterAll` on regular non-static methods.

=== Switching from JUnit 4 to JUnit 5

Enable JUnit 5 support by adding the following line to your `build.gradle` file: 

`build.gradle`
[source,groovy]
----
test {
	useJUnitPlatform()
}
----

Then exclude `junit` from `spring-boot-starter-test` transitive dependencies and add `junit-jupiter-api` and `junit-jupiter-engine` ones.

`build.gradle`
[source,groovy]
----
dependencies {
	testCompile('org.springframework.boot:spring-boot-starter-test') {
		exclude module: 'junit'
	}
	testImplementation('org.junit.jupiter:junit-jupiter-api')
	testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')
}
----

Refresh Gradle configuration, open `BlogApplicationTests` and update imports as bellow and remove `@RunWith(SpringRunner::class)` since `@SpringBootTest` is already annotated with JUnit 5 `@ExtendWith(SpringExtension::class)` as of Spring Boot 2.1.

`src/test/kotlin/blog/BlogApplicationTests.kt`
[source,kotlin]
----
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class BlogApplicationTests {

	@Test
	fun contextLoads() {
	}

}
----

The test should run fine both in command line and in the IDE.

=== Writing JUnit 5 tests in Kotlin

For the sake of this example, let's create an integration test in order to demonstrate various features:

 - We use real sentences between backticks instead of camel-case to provide expressive test function names
 - JUnit 5 allows to inject constructor and method parameters, which is a good fit with Kotlin immutable and non-nullable properties
 - This code leverages `getForObject` and `getForEntity` Kotlin extensions (you need to import them)

`src/test/kotlin/blog/IntegrationTests.kt`
[source,kotlin]
----
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {

	@Test
	fun `Assert blog page title, content and status code`() {
		val entity = restTemplate.getForEntity<String>("/")
		assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
		assertThat(entity.body).contains("<h1>Blog</h1>")
	}

}
----

=== Test instance lifecycle

Sometimes you need to execute a method before or after all tests of a given class. Like Junit 4, JUnit 5 requires by default these methods to be static (which translates to https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects[`companion object`] in Kotlin, which is quite verbose and not straightforward) because test classes are instantiated one time per test.

But Junit 5 allows you to change this default behavior and instantiate test classes one time per class. This can be done in https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-instance-lifecycle[various ways], here we will use a property file to change the default behavior for the whole project:

`src/test/resources/junit-platform.properties`
[source,properties]
----
junit.jupiter.testinstance.lifecycle.default = per_class
----

With this configuration, we can now use `@BeforeAll` and `@AfterAll` annotations on regular methods like shown in updated version of `IntegrationTests` above.

`src/test/kotlin/blog/IntegrationTests.kt`
[source,kotlin]
----
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {

	@BeforeAll
	fun setup() {
		println(">> Setup")
	}

	@Test
	fun `Assert blog page title, content and status code`() {
		println(">> Assert blog page title, content and status code")
		val entity = restTemplate.getForEntity<String>("/")
		assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
		assertThat(entity.body).contains("<h1>Blog</h1>")
	}

	@Test
	fun `Assert article page title, content and status code`() {
		println(">> TODO")
	}

	@AfterAll
	fun teardown() {
		println(">> Tear down")
	}

}
----

== Creating your own extensions

Instead of using util classes with abstract methods like in Java, it is usual in Kotlin to provide such functionalities via Kotlin extensions. Here we are going to add a `format()` function to the existing `LocalDateTime` type in order to generate text with the english date format.

`src/main/kotlin/blog/Extensions.kt`
[source,kotlin]
----
fun LocalDateTime.format() = this.format(englishDateFormatter)

private val daysLookup = (1..31).associate { it.toLong() to getOrdinal(it) }

private val englishDateFormatter = DateTimeFormatterBuilder()
		.appendPattern("yyyy-MM-dd")
		.appendLiteral(" ")
		.appendText(ChronoField.DAY_OF_MONTH, daysLookup)
		.appendLiteral(" ")
		.appendPattern("yyyy")
		.toFormatter(Locale.ENGLISH)

private fun getOrdinal(n: Int) = when {
	n in 11..13 -> "${n}th"
	n % 10 == 1 -> "${n}st"
	n % 10 == 2 -> "${n}nd"
	n % 10 == 3 -> "${n}rd"
	else -> "${n}th"
}

fun String.toSlug() = toLowerCase()
		.replace("\n", " ")
		.replace("[^a-z\\d\\s]".toRegex(), " ")
		.split(" ")
		.joinToString("-")
		.replace("-+".toRegex(), "-")
----

We will leverage this extension in the next section.

== Persistence with JPA

In order to make lazy fetching working as expected, entities should be `open` as described in https://youtrack.jetbrains.com/issue/KT-28525[KT-28525]. We are going to use the Kotlin `allopen` plugin for that purpose.

With Gradle:

`build.gradle`
[source,groovy]
----
apply plugin: 'kotlin-allopen'

allOpen {
	annotation("javax.persistence.Entity")
}
----

Or with Maven:

`pom.xml`
[source,xml]
----
<plugin>
	<artifactId>kotlin-maven-plugin</artifactId>
	<groupId>org.jetbrains.kotlin</groupId>
	<configuration>
		...
		<compilerPlugins>
			...
			<plugin>all-open</plugin>
		</compilerPlugins>
		<pluginOptions>
			<option>all-open:annotation=javax.persistence.Entity</option>
		</pluginOptions>
	</configuration>
</plugin>
----

Then we create our model by using Kotlin https://kotlinlang.org/docs/reference/classes.html#constructors[primary constructor concise syntax] which allows to declare at the same time the properties and the constructor parameters.

`src/main/kotlin/blog/Entities.kt`
[source,kotlin]
----
@Entity
class Article(
		var title: String,
		var headline: String,
		var content: String,
		@ManyToOne var author: User,
		var slug: String = title.toSlug(),
		var addedAt: LocalDateTime = LocalDateTime.now(),
		@Id @GeneratedValue var id: Long? = null)

@Entity
class User(
		var login: String,
		var firstname: String,
		var lastname: String,
		var description: String? = null,
		@Id @GeneratedValue var id: Long? = null)
----

Notice that we are using here our `String.toSlug()` extension to provide a default argument to the `slug` parameter of `Article` constructor. Optional parameters with default values are defined at the last position in order to make it possible to omit them when using positional arguments (Kotlin also supports https://kotlinlang.org/docs/reference/functions.html#named-arguments[named arguments]). Notice that in Kotlin it is not unusual to group concise class declarations in the same file.

NOTE: Here we don't use https://kotlinlang.org/docs/reference/data-classes.html[`data` classes] with `val` properties because JPA is not designed to work with immutable classes or the methods generated automatically by `data` classes. If you are using other Spring Data flavor, most of them are designed to support such constructs so you should use classes like `data class User(val login: String, ...)` when using Spring Data MongoDB, Spring Data JDBC, etc.

NOTE: While Spring Data JPA makes it possible to use natural IDs (it could have been the `login` property in `User` class) via https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.entity-persistence.saving-entites[`Persistable`], it is not a good fit with Kotlin due to https://youtrack.jetbrains.com/issue/KT-6653[KT-6653], that's why it is recommended to always use entities with generated IDs in Kotlin.


We also declare our Spring Data JPA repositories as following.

`src/main/kotlin/blog/Repositories.kt`
[source,kotlin]
----
interface ArticleRepository : CrudRepository<Article, Long> {
	fun findBySlug(slug: String): Article?
	fun findAllByOrderByAddedAtDesc(): Iterable<Article>
}

interface UserRepository : CrudRepository<User, Long> {
	fun findByLogin(login: String): User
}
----

And we write JPA tests to check basic use cases works as expected.

`src/test/kotlin/blog/RepositoriesTests.kt`
[source,kotlin]
----
@DataJpaTest
class RepositoriesTests @Autowired constructor(
		val entityManager: TestEntityManager,
		val userRepository: UserRepository,
		val articleRepository: ArticleRepository) {

	@Test
	fun `When findByIdOrNull then return Article`() {
		val juergen = User("springjuergen", "Juergen", "Hoeller")
		entityManager.persist(juergen)
		val article = Article("Spring Framework 5.0 goes GA", "Dear Spring community ...", "Lorem ipsum", juergen)
		entityManager.persist(article)
		entityManager.flush()
		val found = articleRepository.findByIdOrNull(article.id!!)
		assertThat(found).isEqualTo(article)
	}

	@Test
	fun `When findByLogin then return User`() {
		val juergen = User("springjuergen", "Juergen", "Hoeller")
		entityManager.persist(juergen)
		entityManager.flush()
		val user = userRepository.findByLogin(juergen.login)
		assertThat(user).isEqualTo(juergen)
	}
}
----

NOTE: We use here the `CrudRepository.findByIdOrNull` Kotlin extension provided by default with Spring Data, which is a nullable variant of the `Optional` based `CrudRepository.findById`. Read the great https://medium.com/@elizarov/null-is-your-friend-not-a-mistake-b63ff1751dd5[Null is your friend, not a mistake] blog post for more details.

== Implementing the blog engine

We update the "blog" Mustache templates.

`src/main/resources/templates/blog.mustache`
[source]
----
{{> header}}

<h1>{{title}}</h1>

<div class="articles">

	{{#articles}}
		<section>
			<header class="article-header">
				<h2 class="article-title"><a href="/article/{{id}}">{{title}}</a></h2>
				<div class="article-meta">By  <strong>{{author.firstname}}</strong>, on <strong>{{addedAt}}</strong></div>
			</header>
			<div class="article-description">
				{{headline}}
			</div>
		</section>
	{{/articles}}
</div>

{{> footer}}
----

And we create an "article" new one.

`src/main/resources/templates/article.mustache`
[source]
----
{{> header}}

<section class="article">
	<header class="article-header">
		<h1 class="article-title">{{article.title}}</h1>
		<p class="article-meta">By  <strong>{{article.author.firstname}}</strong>, on <strong>{{article.addedAt}}</strong></p>
	</header>

	<div class="article-description">
		{{article.headline}}

		{{article.content}}
	</div>
</section>

{{> footer}}
----

We update the `HtmlController` in order to render blog and article pages with the formatted date. `ArticleRepository` and `MarkdownConverter` constructor parameters will be automatically autowired since `HtmlController` has a single constructor (implicit `@Autowired`).

`src/main/kotlin/blog/HtmlController.kt`
[source,kotlin]
----
@Controller
class HtmlController(private val repository: ArticleRepository) {

	@GetMapping("/")
	fun blog(model: Model): String {
		model["articles"] = repository.findAllByOrderByAddedAtDesc().map { it.render() }
		return "blog"
	}

	@GetMapping("/article/{slug}")
	fun article(@PathVariable slug: String, model: Model): String {
		val article = repository
				.findBySlug(slug)
				?.render()
				?: throw IllegalArgumentException("Wrong article slug provided")
		model["title"] = article.title
		model["article"] = article
		return "article"
	}

	fun Article.render() = RenderedArticle(
			slug,
			title,
			headline,
			content,
			author,
			addedAt.format()
	)

	data class RenderedArticle(
			val slug: String,
			val title: String,
			val headline: String,
			val content: String,
			val author: User,
			val addedAt: String)

}
----

Then, we add data initialization to a new `BlogConfiguration` class.

`src/main/kotlin/blog/BlogConfiguration.kt`
[source,kotlin]
----
@Configuration
class BlogConfiguration {

    @Bean
    fun databaseInitializer(userRepository: UserRepository,
                            articleRepository: ArticleRepository) = ApplicationRunner {

        val smaldini = userRepository.save(User("smaldini", "Stéphane", "Maldini"))
        articleRepository.save(Article(
                "Reactor Bismuth is out",
                "Lorem ipsum",
                "dolor sit amet",
                smaldini
        ))
        articleRepository.save(Article(
                "Reactor Aluminium has landed",
                "Lorem ipsum",
                "dolor sit amet",
                smaldini
        ))
    }
}
----

And we also update the integration tests accordingly.

`src/test/kotlin/blog/IntegrationTests.kt`
[source,kotlin]
----
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {

	@BeforeAll
	fun setup() {
		println(">> Setup")
	}

	@Test
	fun `Assert blog page title, content and status code`() {
		println(">> Assert blog page title, content and status code")
		val entity = restTemplate.getForEntity<String>("/")
		assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
		assertThat(entity.body).contains("<h1>Blog</h1>", "Reactor")
	}

	@Test
	fun `Assert article page title, content and status code`() {
		println(">> Assert article page title, content and status code")
		val title = "Reactor Aluminium has landed"
		val entity = restTemplate.getForEntity<String>("/article/${title.toSlug()}")
		assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
		assertThat(entity.body).contains(title, "Lorem ipsum", "dolor sit amet")
	}

	@AfterAll
	fun teardown() {
		println(">> Tear down")
	}

}
----

Start (or restart) the web application, and go to `http://localhost:8080/`, you should see the list of articles with clickable links to see a specific article.

== Exposing HTTP API

We are now going to implement the HTTP API via `@RestController` annotated controllers.

`src/main/kotlin/blog/HttpControllers.kt`
[source,kotlin]
----
@RestController
@RequestMapping("/api/article")
class ArticleController(private val repository: ArticleRepository) {

	@GetMapping("/")
	fun findAll() = repository.findAllByOrderByAddedAtDesc()

	@GetMapping("/{slug}")
	fun findOne(@PathVariable slug: String) =
			repository.findBySlug(slug) ?: throw IllegalArgumentException("Wrong article slug provided")

}

@RestController
@RequestMapping("/api/user")
class UserController(private val repository: UserRepository) {

	@GetMapping("/")
	fun findAll() = repository.findAll()

	@GetMapping("/{login}")
	fun findOne(@PathVariable login: String) = repository.findByLogin(login)
}
----

For tests, instead of integration tests, we are going to leverage `@WebMvcTest` and https://mockk.io/[Mockk] wich is similar to https://site.mockito.org/[Mockito] but better suited for Kotlin.

Since `@MockBean` and `@SpyBean` annotations are specific to Mockito, we are going to leverage https://github.com/Ninja-Squad/springmockk[SpringMockK] which provides similar `@MockkBean` and `@SpykBean` annotations for Mockk.

`src/test/kotlin/blog/HttpApiTests.kt`
[source,kotlin]
----
@WebMvcTest
class HttpControllersTests(@Autowired val mockMvc: MockMvc) {

	@MockkBean
	private lateinit var userRepository: UserRepository

	@MockkBean
	private lateinit var articleRepository: ArticleRepository

	@Test
	fun `List articles`() {
		val juergen = User("springjuergen", "Juergen", "Hoeller")
		val spring5Article = Article("Spring Framework 5.0 goes GA", "Dear Spring community ...", "Lorem ipsum", juergen)
		val spring43Article = Article("Spring Framework 4.3 goes GA", "Dear Spring community ...", "Lorem ipsum", juergen)
		every { articleRepository.findAllByOrderByAddedAtDesc() } returns listOf(spring5Article, spring43Article)
		mockMvc.perform(get("/api/article/").accept(MediaType.APPLICATION_JSON))
				.andExpect(status().isOk)
				.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
				.andExpect(jsonPath("\$.[0].author.login").value(juergen.login))
				.andExpect(jsonPath("\$.[0].slug").value(spring5Article.slug))
				.andExpect(jsonPath("\$.[1].author.login").value(juergen.login))
				.andExpect(jsonPath("\$.[1].slug").value(spring43Article.slug))
	}

	@Test
	fun `List users`() {
		val juergen = User("springjuergen", "Juergen", "Hoeller")
		val smaldini = User("smaldini", "Stéphane", "Maldini")
		every { userRepository.findAll() } returns listOf(juergen, smaldini)
		mockMvc.perform(get("/api/user/").accept(MediaType.APPLICATION_JSON))
				.andExpect(status().isOk)
				.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
				.andExpect(jsonPath("\$.[0].login").value(juergen.login))
				.andExpect(jsonPath("\$.[1].login").value(smaldini.login))
	}
}
----

With Gradle:

`build.gradle`
[source,groovy]
----
testImplementation('com.ninja-squad:springmockk:1.1.0')
----

Or with Maven:

`pom.xml`
[source,xml]
----
<dependency>
	<groupId>com.ninja-squad</groupId>
	<artifactId>springmockk</artifactId>
	<version>1.1.0</version>
	<scope>test</scope>
</dependency>
----

NOTE: `$` needs to be escaped in strings as it is used for string interpolation.

== Configuration properties

The recommended way to manage your application properties is to leverage `@ConfigurationProperties`. Immutable properties are https://github.com/spring-projects/spring-boot/issues/8762[not yet supported], but you can use `lateinit var` when you need to deal with non-nullable properties.

`src/main/kotlin/blog/BlogProperties.kt`
[source,kotlin]
----
@ConfigurationProperties("blog")
class BlogProperties {

	lateinit var title: String
	val banner = Banner()

	class Banner {
		var title: String? = null
		lateinit var content: String
	}

}
----

Then we enable it at `BlogApplication` level.

`src/main/kotlin/blog/BlogApplication.kt`
[source,kotlin]
----
@SpringBootApplication
@EnableConfigurationProperties(BlogProperties::class)
class BlogApplication {
	// ...
}
----

To generate https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#configuration-metadata-annotation-processor[your own metadata] in order to get these custom properties recognized by your IDE, https://kotlinlang.org/docs/reference/kapt.html[kapt should be configured] with the `spring-boot-configuration-processor` dependency as following.

`build.gradle`
[source,groovy]
----
apply plugin: 'kotlin-kapt'
dependencies {
	kapt("org.springframework.boot:spring-boot-configuration-processor")
}
----

NOTE: Annotation processing is not yet supported with Maven due to https://youtrack.jetbrains.com/issue/KT-18022[KT-18022], see https://github.com/spring-io/initializr/issues/438[initializr#438] for more details.

In IntelliJ IDEA:

 - Make sure Spring Boot plugin in enabled in menu File | Settings | Plugins | Spring Boot
 - Enable annotation processing via menu File | Settings | Build, Execution, Deployement | Compiler | Annotation Processors | Enable annotation processing
 - Since https://youtrack.jetbrains.com/issue/KT-15040[Kapt is not yet integrated in IDEA], you need to run manually the command `./gradlew kaptKotlin` to generate the metadata

Your custom properties should now be recognized when editing `application.properties` (autocomplete, validation, etc.).

`src/main/resources/application.properties`
[source,properties]
----
blog.title=Blog
blog.banner.title=Warning
blog.banner.content=The blog will be down tomorrow.
----

Edit the template and the controller accordingly.

`src/main/resources/templates/blog.mustache`
[source]
----
{{> header}}

<div class="articles">

	{{#banner.title}}
	<section>
		<header class="banner">
			<h2 class="banner-title">{{banner.title}}</h2>
		</header>
		<div class="banner-content">
			{{banner.content}}
		</div>
	</section>
	{{/banner.title}}

	...

</div>

{{> footer}}
----

`src/main/kotlin/blog/HtmlController.kt`
[source,kotlin]
----
@Controller
class HtmlController(private val repository: ArticleRepository,
					 private val properties: BlogProperties) {

	@GetMapping("/")
	fun blog(model: Model): String {
		model["title"] = properties.title
		model["banner"] = properties.banner
		model["articles"] = repository.findAllByOrderByAddedAtDesc().map { it.render() }
		return "blog"
	}

	// ...
----

Restart the web application, refresh `http://localhost:8080/`, you should see the banner on the blog homepage.

== Conclusion

We have now finished to build this sample Kotlin blog application. The source code https://github.com/spring-guides/tut-spring-boot-kotlin[is available on Github]. You can also have a look to https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#kotlin[Spring Framework] and https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-kotlin.html[Spring Boot] reference documentation if you need more details on specific features.
