Getting started with Spring Boot and Kotlin

Who am I?

- 🇧🇷🇵🇹 Software Developer
- Working for 2 years in Germany
Lucas Felix de Sousa
Software ArchitectÂ

Agenda
- Kotlin
- Basics
- Null Safety
- Extensions
- Spring Framework
- Dependency Injection and IoC
- Spring Boot
- Configuration
- Rest Controller
- Error Handling
- Demo

Kotlin
- Created by JetBrains in 2011
- Designed to be compatible with Java
// Function with default parameters
fun greet(name: String = "stranger") {
// String interpolation
println("Hello $name")
}
fun main() {
greet("Coding Leipzig") // Hello Coding Leipzig
greet() // Hello stranger
}// Top level functions, functions without a class
fun main() = println("Hello, world!")Kotlin
// var can be reassigned (get/set)
// val is readonly (get)
class Person(val name: String, var nationality: String = "unknown") {
fun print() = println("Name: $name, Nationality: $nationality")
}
fun main() {
val lucas = Person(name = "Lucas")
lucas.print() // Name: Lucas, Nationality: unknown
lucas.nationality = "BR"
lucas.print() // Name: Lucas, Nationality: BR
lucas.name = "some" // Compiler error, val cannot be reassigned
}NullPointerException

private static void someMethod(String param) {
System.out.println(param.length);
}
public static void main(String[] args) {
someMethod("abc");
someMethod(null); // NullPointerException
}Kotlin Null Safety
// '?' makes any class Nullable
fun someMethod(param: String?) {
// '?.' null safe access to methods and properties
println(param?.length)
}
fun main() {
someMethod("abc")
someMethod(null) // Prints null
}- A common problem in the Java environment
- Kotlin has different types for nullable and not-nullable objects
private static void someMethod(String param) {
System.out.println(param.length);
}
public static void main(String[] args) {
someMethod("abc");
someMethod(null); // NullPointerException
}fun someMethod(param: String) {
println(param.length)
}
fun main() {
someMethod("abc")
someMethod(null) // Compiler error
}Kotlin Null Safety - Elvis Operator
Better way to handle null values
fun hello(someone: String?) {
// we can use it for applying a default value
val name: String = someone ?: "guest"
println("Hello $name")
}fun getPerson(id: Long) : Person? {
// return the person or null if doesn't exist
}
fun assertPersonExists(id: Long) {
// we can also use it for throwing an exception when is null
getPerson(id) ?: throw RuntimeException("Person with $id doesn't exist")
}
Kotlin Extensions
Extending class functionality
fun String.lastChar() {
return this.get(this.lastIndex)
}
fun List<Any>.printAll() {
for (s in this) {
println(s)
}
}
fun Int.sum(n : Int) : Int = this + n
fun main() {
println("lucas".lastChar())
listOf(1, 2, 3, 4, 5).printAll()
listOf("a", "b", "c").printAll()
println(1.sum(2))
}
Try Kotlin
Inversion of Control
Hollywood Principle: Don't call us, we'll call you
class MovieLister {
var finder : MovieFinder = FileMovieFinder("movies.txt")
}class MovieLister(val finder: MovieFinder)- Loose coupling
- Easier to change implementation
- Increase Testability using mocks
interface MovieFinder {
fun findAll() : List<Movie>
}
class FileMovieFinder(val file: String): MovieFinder {
override fun findAll(): List<Movie> {
// list movies from file
}
}
class IMDBMovieFinder(): MovieFinder {
override fun findAll(): List<Movie> {
// list movies from IMDB
}
}Spring Framework
- Created in 2002
- Dependency Injection
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");Spring Framework - Creating Beans
Better way to configure beans
@Configuration
class SpringConfig {
@Bean
fun movieLister(): MovieLister {
return MovieLister(FileMovieFinder("movies.txt"))
}
}@Component
class IMDBMovieFinder(): MovieFinder {
override fun findAll(): List<Movie> {
// list movies from file
}
}Creates a bean manually
Creates a bean and inject dependencies automatically for this class
Configure Spring Beans manually
Spring Framework - Injecting dependencies
Declaring dependencies
@Component
class MovieLister {
@Autowired
var finder: MovieFinder?
}@Component
class MovieLister(val finder: MovieFinder)Inject dependency using setter
Inject dependency using constructor
The Spring team recommends constructor injection:
- Immutable objects
- Required dependencies are not null
- Increase testability
Configuration Hell
- Configure servlet.xml
- Configure web.xml
- Configure web server
- Deploy WAR file

Spring Boot
- Starts Tomcat embedded server
- Automatically configure Spring and many 3rd dependencies
- No XML configuration
- Creates runnable JAR file

@SpringBootApplication
@RestController
class KotlinSpringBootApplication {
@GetMapping("/")
fun root() = "Hello World"
}
fun main() {
runApplication<KotlinSpringBootApplication>()
}Spring Boot Configuration
Add starter POM and configure
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency># Server HTTP port.
server.port=8080Adding Dependendency
Configuring
pom.xml
application.properties
Spring Boot Configuration
Add starter POM and configure
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency># JDBC URL of the database.
spring.datasource.url=
# Login username of the database.
spring.datasource.username=
# Login password of the database.
spring.datasource.password=
# Additional native properties for JPA
spring.jpa.properties.*=Adding Dependendency
Configuring
pom.xml
application.properties
Try Spring Boot
Spring Web and Rest Controller
Creating a REST API
@RestController
@RequestMapping("/something")
class MyFirstRestApi(private val service: MyService) {
@GetMapping
fun list(@RequestParam param1) {
// doSomething
}
}Spring will manage this class and inject the dependencies
GET /something
Injected by Spring
Adds query parameter to variable param1
GET /something?param1=value
Spring Web and Rest Controller
Creating a REST API
@RestController
@RequestMapping("/something")
class MyFirstRestApi(private val service: MyService) {
@GetMapping("/{id}")
fun get(@PathVariable id: Long) {
// Do something
}
@DeleteMapping("/{id}")
@ResponseStatus(NO_CONTENT)
fun delete(@PathVariable id: Long) {
// Do something
}
}GET /something/{id}
DELETE /something/{id}
Default HTTP status is OK, this annotation can change it
Add value of {id} to the variable
Spring Web and Rest Controller
Creating a REST API
@RestController
@RequestMapping("/something")
class UserController(private val service: MyService) {
@PostMapping
@ResponseStatus(CREATED)
fun add(@RequestBody @Valid someData: AddData) {
// Do something
}
}POST /something
This method will receive a body and convert it to AddData class
Error Handling with Spring
To create a generic error handling for Exceptions is also an easy task
class CustomError(val message: String?)
@RestControllerAdvice
class CustomExceptionHandler {
@ExceptionHandler(ResourceNotFoundException::class)
@ResponseStatus(HttpStatus.NOT_FOUND)
fun notFound(exception: ResourceNotFoundException) {
return CustomError(exception.message)
}
}
Demo

Next steps:
To know more:
Questions?

Thank you :)

Getting started with Spring Boot and Kotlin
By Lucas Felix
Getting started with Spring Boot and Kotlin
- 457