More posts by Intelliware Development
On an effort to leverage Kotlin for our projects, earlier this year we had a study group with the goal to learn more about this development language, that’s receiving increasing attention and adoption in the industry. The study group was in partnership with one of our clients, which is already using Kotlin on their projects, and the interest it created among my Intelliware colleges motivated me to create a Kotlin lab, showing how to create a Kotlin Spring Boot app. The lab has the advantage of a more condensed format, compared to a study group, able to give the participants the opportunity to create an application from scratch in a little bit more than an hour, without any previous knowledge of the language.
I created this post with the lab content with the hope that it can be useful to a bigger audience, be it a developer trying to learn Kotlin by himself or a group willing to go through the lab together. The content is inspired by Spring Boot Kotlin Tutorial, with some of its content adapted to a lab format and specific “understanding the code” sections helping the participant understand the language concepts used.
STEP 1: Install IntelliJ
Kotlin is a language developed by JetBrains, the company behind IntelliJ, so even though you can use any text editor, IntelliJ is recommended due to better integration with the language.
Click here to download and install the Ultimate or Community edition of IntelliJ.
Step 2: Bootstrap your application
- Go to Spring Initializr
- Select Kotlin as a language
- Use “blog” for Artifact
- For dependencies, select: Web, JPA, and H2
5. Click on Generate Project
6. Unpack the downloaded project
7. On command line run the application with ./mvnw spring-boot:run
Step 3: Import the project on IntelliJ
- File -> new -> Project from existing sources
- Select the project folder
- Chose “Import project from external model” -> Maven
- Follow the next screens and Finish
Step 4: Look at the application bootstrapped
- Open the file
com.example.blog.BlogApplication
. There are a few things you will notice:- Lack of semicolons
- Since the class has no body, the curly braces can be omitted
- The
main
function is a top-level function, meaning there’s no need to create a class to hold it, like languages such as Java, C# or Scala - The default visibility is
public
, which can be omitted for the main function - If you navigate to the declaration of
runApplication
, you’ll see that it’s declared in a Kotlin extension class. It’s part of the Spring Boot Kotlin support, enabling writing more idiomatic code
- Open the
pom.xml
file. There are a few things you will notice:kotlin-maven-plugin
: used to compile Kotlin code.sourceDirectory
andtestSourceDirectory
are also configuredkotlin-maven-allopen
: Kotlin has classes and their membersfinal
by default, which makes it inconvenient to use frameworks such as Spring that require classes to be open. The all-open plugin, which has Spring support, makes classes annotated with a specific annotation and their members open without the explicit open keyword.
Step 5: Create the first Rest Resource
- Implement the class
HelloWorldResource
- Re-run the application with
./mvnw spring-boot:run
- Open your browser on http://localhost:8080/hello. You should see “Hello” on the page displayed.
Understanding the code
hello()
is a single-expression function, so the curly braces can be omitted- For single-expression functions, explicitly declaring the return type is optional when this can be inferred by the compile.
Step 6: Create the Article model and Resources
- Implement the
Article
class with the propertiestitle
andcontent
- Implement the
ArticleResource
Rest endpoint returning a list of Articles. - Re-run the application with
./mvnw spring-boot:run
- Open your browser on http://localhost:8080/article. You should see the JSON representation of the list returned
Understanding the code
Article
- Is a class whose main purpose is to hold data, making it a good candidate to be a Data Class, which automatically provide
equals()
,hashCode()
,toString()
,componentN()
andcopy()
functions - It uses its primary constructor to declare and initialize its properties in a concise way. Properties declared in the primary constructor can be mutable (
var
) or read-only (val
)
- Is a class whose main purpose is to hold data, making it a good candidate to be a Data Class, which automatically provide
ArticleResource
- To create instances of the
Article
class, we call the constructor as if it was a regular function - Kotlin does not have a
new
keyword listOf
function is part of Kotlin Standard Library, which provides living essentials for everyday work with Kotlin- You didn’t have to import
listOf
. Just like Java hasjava.lang
, Kotlin has some packages that are imported by default.
- To create instances of the
Step 7: Add Article properties with default values
- Add the properties
createdAt
of typeLocalDateTime
andid
of typeLong?
with default values - Re-run the application with
./mvnw spring-boot:run
- Open your browser on http://localhost:8080/article. You should see the new properties on the objects in the list
Understanding the code
- Function arguments can have default values, which are used when a corresponding argument is omitted
- Kotlin’s type system is aimed at eliminating the danger of null references from code. Since the
Article.id
is only specified when it’s persisted (to be implemented in a following section), its supposed to allownull
, so the nullableLong?
is used - Since we are satisfied with the default values of the new parameters, we do not need to change the
Article
instantiation onArticleget.getArticles()
Step 8: Test with JUnit 5
While JUnit 4 is still the default testing framework provided with Spring Boot, and can be used with Kotlin, JUnit 5 provides features handy with Kotlin, including autowiring of constructor / method parameters which allows to use non-nullable val
properties and the possibility to use @BeforeAll
/@AfterAll
on regular non-static methods. Follow the steps below, or, to make it easier, see the necessary changes in this diff or the expected final file content: pom.xml
and BlogApplicationTests.kt
- Exclude
junit
Maven transitive dependency fromspring-boot-starter-test
- Add
junit-jupiter-engine
Maven dependency - Add
junit-platform-surefire-provider
Maven dependency tomaven-surefire-plugin
- Refactor
BlogApplicationTests.kt
to Junit 5 - Run
./mvnw clean install
and check if the build is still successful
STEP 9: Add test to ArticleResource
- Implement the
ArticleResourceTest
. Make sure to put it in thesrc/test/kotlin/com/example/blog/
folder. This short test is enough for the purpose of this lab, but I hope in real life you test more than the result size - Run
./mvnw clean install
and check if the test runs and the build is still successful
Understanding the code
- We’re using
SpringExtension
which is able to inject dependencies into test constructors. This makes it a good fit with Kotlin immutable and non-nullable properties - We use real sentences in test function names. Backticks are part of the language to help with the Java interop but they also help writing more expressive test function names, instead of the usual camel-case naming
getForEntity
is another Spring Kotlin extension. It takes advantage of Kotlin reified type parameters, overcoming Java type erasure limitation which would require the usage ofParameterizedTypeReference<List<Article>>
response.body?.size
is a safe way of accessing the nullablebody
property. It will returnsize
ifbody
is not null, and null otherwise. Other ways are also available, such asif
statments and the Elvis operator
Step 10: Persistence with JPA
- Annotate
Article
with@Entity
andArticle.id
with@Id @GeneratedValue
. Final result:Article
- Implement
ArticleRepository
- Use the
ArticleRepository
to retrieve the list of Articles onArticleResource
- Add the Kotlin JPA plugin and add
kotlin-maven-noarg
dependency to the pom.xml` - Re-run the application with
./mvnw spring-boot:run
- Open your browser on http://localhost:8080/article. The result is not very exciting and you won’t see anything since the database is empty. We’ll solve this on next section.
Understanding the code
- JPA annotations can be used in the primary constructors, contributing for a concise code
- Primary constructors will also have its dependencies automatically autowired, which is the case of
ArticleResource
- JPA requires the entities to have a zero-argument constructor. Since we added the primary constructor to
Article
, the entity is no longer satisfying that requirement. Kotlin no-arg plugin with JPA support adds a zero-argument constructor for classes annotated with@Entity
,@Embeddable
and@MappedSuperclass
Step 11: Add some Articles to the database
- Implement the function
BlogApplication.initDatabase()
- Re-run the application with
./mvnw spring-boot:run
- Open your browser on http://localhost:8080/article. Now you should see some Articles on the page
Understanding the code
- Now that
BlogApplication
has a body, it needs curly braces - The function
initDatabase
produces a@Bean
of typeCommandLineRunner
which implements a callback to run specific pieces of code when an application is fully started CommandLineRunner
is aFunctionalInterface
, meaning it’s a Single Abstract Method (SAM) interface, which can be automatically converted from Kotlin function literals. If it got too complicated, the bottom line is the Kotlin support for functional programming allows us to implement the method the way we did, instead of having to explicitly declare a class to implement a single method
So that’s it for now, even though we haven’t implemented the most exciting application, the small portion of code we wrote is a starting point for getting more familiar with Kotlin and how it integrates with Spring Boot. We also saw language features such as, data classes, primary constructors, Kotlin Standard Library, default imports, function parameters, default values, nullable and non-nullable types, reified type parameters, lambda expressions and function literals, JUnit 5 and JPA integration, Kotlin Maven plugins and Spring Kotlin extensions.
The complete source code can be found at kotlin-spring-boot-lab.
About The Author: Andrea Ramirez
More posts by Andrea Ramirez