Kotlin with Spring Boot Setup
Tags: kotlin, spring, gradle, jpa
Published: 2023-03-09 17:49:19

As we known, Kotlin has a compiler for the JVM platform, which means all the codes written in Kotlin can run on the JVM. Therefore, even though Spring itself is written entirely in Java, Spring applications could be written in Java or/and in Kotlin. However, Java and Kotlin are different languages, that means a Spring application written in Kotlin requires an extra configuration.

## Additional dependencies
- `kotlin-stdlib-jdk8`: This dependency includes a variant of the standard Java 8 library to Kotlin with the required classes (needed for compatibility of Java and Kotlin).
- `kotlin-reflect`: Spring often uses reflection, for example, to create proxy classes, but Java and Kotlin objects are various. Therefore, we have to work with them differently. This dependency adds the ability for Spring to work with objects by reflection.
- `jackson-module-kotlin`: Java and Kotlin objects have different internal structures. The standard Jackson serializer for Java may not handle Kotlin objects in some cases. Specifically, this library add support for **introspection** of Kotlin method/constructor parameter names, without having to add explicit property name annotation.
Assuming we are using Gradle with Kotlin DSL, including these plugins would looks like:

``` kotlin
dependencies {
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
}
```

> **_Note:_** You can use shorthand for a dependency on a Kotlin module, for example, `kotlin("test")` for `"org.jetbrains.kotlin:kotlin-test"`
```kotlin
dependencies {
    implementation(kotlin("reflect:1.8.10"))
    implementation(kotlin("stdlib-jdk8:1.8.10"))
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
}
```

## Additional plugins
### all-open plugin
In Koltin, classes and their members are `final` by default. And as you may know, Spring inherits from our classes/interfaces to create `proxy classes` and overrides some methods at the runtime (ex: interfaces extending `CrudRepository`, classes using `@Transactional` annotation…).
This means, we need to mark almost “everything” with the `open` modifier, and that could be annoying.

`all-open` plugin is here to the rescue! It make Kotlin classes annotated with a specific annotation and their members open, without using the modifier `open` explicitly.

``` kotlin
plugins {
    kotlin("plugin.allopen") version "1.8.10" // check the latest version
}
```
Now we just need to specify these annotations in an `allOpen` block in the Gradle build file :

``` kotlin
allOpen {
    annotation("org.springframework.stereotype.Repository")
    annotation("org.springframework.transaction.annotation.Transactional")
    annotation("org.springframework.context.annotation.Configuration")
    annotation("com.example.annotation.SuperAnnotation")
    //...
}
```
Cool, right ?
Still, that’s boilerplate work, we will have to remember it whenever we create a new project, or we will end-up by *copy/pasting* it each time, or…
The ultimate solution for all this is called `kotlin-spring` plugin.

### kotlin-spring plugin
``` kotlin
plugins {
    kotlin("plugin.spring") version "1.8.10"
}
```
The `kotlin-spring` plugin is a wrapper on top of `all-open` plugin. By using it, you can omit listing Spring annotations manually in an `allOpen` block. The plugin specifies the following annotations:

- `@Component`
- `@Transactional`
- `@Async`
- `@Cacheable`
- `@SpringBootTest`

And thanks to meta-annotations support, classes annotated with : `@Configuration`, `@Controller`, `@RestController`, `@Service`, `@Repository` are automatically opened since these annotations are meta-annotated with `@Component`.
Moreover, we still can have an `allOpen` block and list other annotations if we need that.
> _**Note:**_ If you use the project template generated by start.spring.io, the kotlin-spring plugin will be enabled by default.

### no-arg plugin
`no-arg` plugin generates an additional **zero-argument constructor** for some classes, the selection of these classes is done the same way it’s done with `all-open` plugin; The plugin is looking for classes annotated with a special annotation.
To use the plugin, we’ll have to start by including it in our build file :

``` kotlin
plugins {
    kotlin("plugin.noarg") version "1.8.10"
}
```
Then, similar to the `allOpen` block related to `all-open` plugin, we need to add a `noArg` block :

``` kotlin
noArg {
    annotation("org.example.SomeAnnotation")
    //...
}
```
This feature could be useful when we want to use Java Persistence API, it allows JPA to instantiate a class although it doesn’t have a zero-argument constructor. We just need to list the right annotations from JPA. Let’s see how we could do it in a better way with the next plugin.

### kotlin-jpa plugin
As with the `kotlin-spring` plugin wrapped on top of `all-open`, `kotlin-jp` is wrapped on top of `no-arg`. The plugin specifies the following annotations as *no-arg* annotations automatically :
- `@Entity`
- `@Embeddable`
- `@MappedSuperclass`

``` kotlin
plugins {
    kotlin("plugin.jpa") version "1.8.10"
}
```

I hope this was helpful. And thanks for reading.
<img width="100%" style="width:100%" src="https://media.giphy.com/media/YybKRCSHL1OBW/giphy.gif" />