SlideShare a Scribd company logo
‹#›© 2016 Pivotal Software, Inc. All rights reserved. ‹#›© 2016 Pivotal Software, Inc. All rights reserved.
Spring ❤ Kotlin
Toshiaki Maki (@making)
tmaki@pivotal.io
JJUG Night Seminar 2017 Feb
2017-02-20
© 2016 Pivotal Software, Inc. All rights reserved.
Who am I ?
• Toshiaki Maki (@making) https://ik.am
• Sr. Solutions Architect @Pivotal
• Spring ☘ / Cloud Foundry ☁ / Concourse ✈ / BOSH 🐚
bit.ly/hajiboot2
© 2016 Pivotal Software, Inc. All rights reserved.
Agenda
•Spring Boot with Kotlin
•Kotlin support in Spring 5
‹#›© 2016 Pivotal Software, Inc. All rights reserved.
Spring Boot with Kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Initializr
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Initializr
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
package com.example



import org.springframework.boot.SpringApplication

import org.springframework.boot.autoconfigure.SpringBootApplication



@SpringBootApplication

class DemoApplication



fun main(args: Array<String>) {

SpringApplication.run(DemoApplication::class.java, *args)

}

© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
package com.example



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

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



@RestController

class HelloController {

@GetMapping("/")

fun hello() = "Hello World!"

}


© 2016 Pivotal Software, Inc. All rights reserved.
package com.example



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

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



@RestController

class HelloController {

@GetMapping("/")

fun hello() = "Hello World!"

}


© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
open class AppConfig {

@Bean

open fun restTemplate() = RestTemplate()

}
© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
open class AppConfig {

@Bean

open fun restTemplate() = RestTemplate()

}
👇
👇
© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
open class AppConfig {

@Bean

open fun restTemplate() = RestTemplate()

}
👇
👇
😩
© 2016 Pivotal Software, Inc. All rights reserved.
Cglib and Spring
// Java
class AppConfig {

@Bean

RestTemplate restTemplate() {
return new RestTemplate();
}

}
© 2016 Pivotal Software, Inc. All rights reserved.
Cglib and Spring
// Java
class AppConfig {

@Bean

RestTemplate restTemplate() {
return new RestTemplate();
}

}
Singleton
© 2016 Pivotal Software, Inc. All rights reserved.
Cglib and Spring (Pseudo Code)
class AppConfig$$ extends AppConfig {
@Override

RestTemplate restTemplate() {
if (context.contains("restTemplate")) {
return context.get("restTemplate");
}
return super.restTemplate();
}

}
© 2016 Pivotal Software, Inc. All rights reserved.
Cglib and Spring (Pseudo Code)
class AppConfig$$ extends AppConfig {
@Override

RestTemplate restTemplate() {
if (context.contains("restTemplate")) {
return context.get("restTemplate");
}
return super.restTemplate();
}

}
Methods in Kotlin
are final by default !!
open removes final
© 2016 Pivotal Software, Inc. All rights reserved.
<plugin>

<artifactId>kotlin-maven-plugin</artifactId>

<groupId>org.jetbrains.kotlin</groupId>

<version>${kotlin.version}</version>

<configuration>

<compilerPlugins>

<plugin>spring</plugin>

</compilerPlugins>

</configuration>
</plugin>
© 2016 Pivotal Software, Inc. All rights reserved.
open class AppConfig {

@Bean

open fun restTemplate() = RestTemplate()

}
© 2016 Pivotal Software, Inc. All rights reserved.
open class AppConfig {

@Bean

open fun restTemplate() = RestTemplate()

}
© 2016 Pivotal Software, Inc. All rights reserved.
class AppConfig {

@Bean

fun restTemplate() = RestTemplate()

}
© 2016 Pivotal Software, Inc. All rights reserved.
class AppConfig {

@Bean

fun restTemplate() = RestTemplate()

}
😍
© 2016 Pivotal Software, Inc. All rights reserved.
http://start.spring.io/#!language=kotlin
‹#›© 2016 Pivotal Software, Inc. All rights reserved.
Kotlin support in Spring 5
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Framework 5
•Java 8 baseline, Java 9 compatibility
•Reactive Support & Spring WebFlux
•Router Functions
•Performance improvements
•HTTP/2 support
•Kotlin support
© 2016 Pivotal Software, Inc. All rights reserved.
Kotlin Support
© 2016 Pivotal Software, Inc. All rights reserved.
Kotlin Support
© 2016 Pivotal Software, Inc. All rights reserved.
Kotlin Support
•Extension Functions
•Reified type parameters
© 2016 Pivotal Software, Inc. All rights reserved.
Kotlin Support
•Extension Functions
•Reified type parameters
🤔
© 2016 Pivotal Software, Inc. All rights reserved.
package com.example;
public class Foo {
public <T> T create(Class<T> clazz) {
try {
return clazz.newInstance();
}
catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
© 2016 Pivotal Software, Inc. All rights reserved.
// Java
Foo foo = new Foo();
Bar bar = foo.create(Bar.class);
© 2016 Pivotal Software, Inc. All rights reserved.
// Java
Foo foo = new Foo();
Bar bar = foo.create(Bar.class);
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class.java)
© 2016 Pivotal Software, Inc. All rights reserved.
// Java
Foo foo = new Foo();
Bar bar = foo.create(Bar.class);
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class.java)
👇
© 2016 Pivotal Software, Inc. All rights reserved.
KClass
Bar::class // kotlin.reflect.KClass
Bar::class.java // java.lang.Class

© 2016 Pivotal Software, Inc. All rights reserved.
Extension Functions
•Extends a class with new functionality
without having to inherit from the class
•https://kotlinlang.org/docs/reference/
extensions.html#extension-functions
© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class.java)
© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class.java)
© 2016 Pivotal Software, Inc. All rights reserved.
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class)
© 2016 Pivotal Software, Inc. All rights reserved.
Extension Functions
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class)
© 2016 Pivotal Software, Inc. All rights reserved.
Extension Functions
package com.example
import kotlin.reflect.KClass
fun <T : Any> Foo.create(kclass: KClass<T>)
= create(kclass.java)

FooExtensions.kt
© 2016 Pivotal Software, Inc. All rights reserved.
Extension Functions
package com.example
import kotlin.reflect.KClass
fun <T : Any> Foo.create(kclass: KClass<T>)
= create(kclass.java)

👇
FooExtensions.kt
© 2016 Pivotal Software, Inc. All rights reserved.
Extension Functions
// Kotlin
val foo = Foo()
val bar = foo.create(Bar::class)
😍
© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
•Access a type passed to us as a parameter
•https://kotlinlang.org/docs/reference/inline-
functions.html#reified-type-parameters
© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
inline fun <reified T : Any> Foo.create()
= create(T::class.java)

© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
inline fun <reified T : Any> Foo.create()
= create(T::class.java)
👇
👇
© 2016 Pivotal Software, Inc. All rights reserved.
val foo = Foo()
val bar = foo.create(Bar::class)

© 2016 Pivotal Software, Inc. All rights reserved.
val foo = Foo()
val bar = foo.create(Bar::class)

© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
val foo = Foo()
val bar = foo.create<Bar>()

😍
© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
val foo = Foo()
val bar: Bar = foo.create()

😍
© 2016 Pivotal Software, Inc. All rights reserved.
Reified type parameters
val foo = Foo()
val bar: Bar = foo.create()

😍
"idiomatic Kotlin code"
© 2016 Pivotal Software, Inc. All rights reserved.
"idiomatic Kotlin code" with Spring 5
© 2016 Pivotal Software, Inc. All rights reserved.
Application Context
// Java
ApplicationContext context = ...;
Bar bar = context.getBean(Bar.class);
© 2016 Pivotal Software, Inc. All rights reserved.
Application Context (Extension)
// Kotlin
val context = ...
val bar = context.getBean(Bar::class)

© 2016 Pivotal Software, Inc. All rights reserved.
Application Context (Reified Type)
// Kotlin
val context = ...
val bar = context.getBean<Bar>()

© 2016 Pivotal Software, Inc. All rights reserved.
Application Context (Reified Type)
// Kotlin
val context = ...
val bar: Bar = context.getBean()

© 2016 Pivotal Software, Inc. All rights reserved.
JdbcTemplate
// Java
Long count = jdbcTemplate
.queryForObject("SELECT count(*) FROM foo"
, Long.class);
© 2016 Pivotal Software, Inc. All rights reserved.
JdbcTemplate (Extension)
// Kotlin
val count = jdbcTemplate
.queryForObject("SELECT count(*) FROM foo"
, Long::class)
© 2016 Pivotal Software, Inc. All rights reserved.
JdbcTemplate (Reified Type)
// Kotlin
val count = jdbcTemplate
.queryForObject<Long>(
"SELECT count(*) FROM foo")
© 2016 Pivotal Software, Inc. All rights reserved.
JdbcTemplate (Reified Type)
// Kotlin
val count: Long = jdbcTemplate
.queryForObject("SELECT count(*) FROM foo")
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate
// Java
String foo = restTemplate
.getForObject("http://abc.io",String.class);
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate (Reified Type)
// Kotlin
val foo = restTemplate
.getForObject<String>("http://abc.io");
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate (Reified Type)
// Kotlin
val foo: String = restTemplate
.getForObject("http://abc.io");
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate
// Java
List<Foo> foos = restTemplate
.getForObject("http://abc.io",
List<Foo>.class);
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate
// Java
List<Foo> foos = restTemplate
.getForObject("http://abc.io",
List<Foo>.class);
Compile Error!
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate
// Java
List<Foo> foos = restTemplate
.exchange("http://abc.io", HttpMethod.GET,
null, new
ParameterizedTypeReference<List<Foo>>()
{}).getBody();
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate
// Java
List<Foo> foos = restTemplate
.exchange("http://abc.io", HttpMethod.GET,
null, new
ParameterizedTypeReference<List<Foo>>()
{}).getBody();
💩
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate (Reified Type)
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate (Reified Type)
// Kotlin
val foos: List<Foo> = restTemplate
.getForObject("http://abc.io");
© 2016 Pivotal Software, Inc. All rights reserved.
RestTemplate (Reified Type)
// Kotlin
val foos: List<Foo> = restTemplate
.getForObject("http://abc.io");
😍
© 2016 Pivotal Software, Inc. All rights reserved.
Spring ❤ Kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Framework 5
•Java 8 baseline, Java 9 compatibility
•Reactive Support & Spring WebFlux
•Router Functions
•Performance improvements
•HTTP/2 support
•Kotlin support
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Framework 5
•Java 8 baseline, Java 9 compatibility
•Reactive Support & Spring WebFlux
•Router Functions
•Performance improvements
•HTTP/2 support
•Kotlin support
👇
👇
© 2016 Pivotal Software, Inc. All rights reserved.
Spring Framework 5
•Java 8 baseline, Java 9 compatibility
•Reactive Support & Spring WebFlux
•Router Functions
•Performance improvements
•HTTP/2 support
•Kotlin support
👇
👇
🤔
© 2016 Pivotal Software, Inc. All rights reserved.
© 2016 Pivotal Software, Inc. All rights reserved.
WebMVC + @Controller in Java
@RestController
public class UserController {
private final UserRepository repo;
UserController(UserRepository repo) {/.../}
@GetMapping
List<User> users() {
return repo.findAll();
}
}
© 2016 Pivotal Software, Inc. All rights reserved.
WebFlux + @Controller in Java
@RestController
public class UserController {
private final ReactiveUserRepository repo;
UserController(ReactiveUserRepository repo) {/.../}
@GetMapping
Flux<User> users() {
return repo.findAll();
}
}
© 2016 Pivotal Software, Inc. All rights reserved.
WebFlux + @Controller in Java
@RestController
public class UserController {
private final ReactiveUserRepository repo;
UserController(ReactiveUserRepository repo) {/.../}
@GetMapping
Flux<User> users() {
return repo.findAll();
}
}
Non-Blocking!!
© 2016 Pivotal Software, Inc. All rights reserved.
WebFlux + RouterFunction in Java
© 2016 Pivotal Software, Inc. All rights reserved.
WebFlux + RouterFunction in Java
RouterFunction<?> routes =
route(GET("/users"), req -> ok()
.body(repo.findAll(), User.class));
© 2016 Pivotal Software, Inc. All rights reserved.
WebFlux + RouterFunction in Kotlin
{
accept(APPLICATION_JSON).apply {
GET("/users",{
ok().body(fromPublisher(repo.findAll())
})
}
}
© 2016 Pivotal Software, Inc. All rights reserved.
Check source code!!
• https://github.com/mix-it/mixit
• https://github.com/making/demo-router-functions
© 2016 Pivotal Software, Inc. All rights reserved.
Other Kotlin Support
•Functional Bean Registration with Kotlin
•WebFlux functional API, the Kotlin way
•Leveraging Kotlin nullable information
•Kotlin Script based templates
•...
•https://speakerdeck.com/sdeleuze/functional-
web-applications-with-kotlin-and-spring-5?
© 2016 Pivotal Software, Inc. All rights reserved.
Release date
https://jira.spring.io/browse/SPR
© 2016 Pivotal Software, Inc. All rights reserved.
http://start.spring.io/#!language=kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
http://start.spring.io/#!language=kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
http://start.spring.io/#!language=kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
http://start.spring.io/#!language=kotlin
© 2016 Pivotal Software, Inc. All rights reserved.
Resources
• https://spring.io/blog/2017/01/04/introducing-kotlin-support-
in-spring-framework-5-0
• https://speakerdeck.com/sdeleuze
• https://blog.ik.am/entries/407
© 2016 Pivotal Software, Inc. All rights reserved.
CfP for JJUG CCC 2017 Spring
•Submit Call for Paper!!! 🙇
•http://www.java-users.jp/?p=2830

More Related Content

What's hot (20)

PDF
Short Lived Tasks in Cloud Foundry #cfdtokyo
Toshiaki Maki
 
PDF
Why PCF is the best platform for Spring Boot
Toshiaki Maki
 
PDF
Spring Framework 5.0による Reactive Web Application #JavaDayTokyo
Toshiaki Maki
 
PDF
Introduction to Concourse CI #渋谷Java
Toshiaki Maki
 
PDF
Event Driven Microservices with Spring Cloud Stream #jjug_ccc #ccc_ab3
Toshiaki Maki
 
PDF
Microservices with Spring and Cloud Foundry
Alain Sahli
 
PDF
From Spring Boot 2.2 to Spring Boot 2.3 #jsug
Toshiaki Maki
 
PDF
Introduction to Spring WebFlux #jsug #sf_a1
Toshiaki Maki
 
PDF
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
Toshiaki Maki
 
PPTX
マイクロサービスに必要な技術要素はすべてSpring Cloudにある #DO07
Toshiaki Maki
 
PDF
今すぐ始めるCloud Foundry #hackt #hackt_k
Toshiaki Maki
 
PDF
クラウド時代の Spring Framework (aka Spring Framework in Cloud Era)
Tsuyoshi Miyake
 
PDF
Spring5 New Features - Nov, 2017
VMware Tanzu Korea
 
PDF
Serverless with Spring Cloud Function, Knative and riff #SpringOneTour #s1t
Toshiaki Maki
 
PDF
Spring Cloud Stream with Kafka
David Kiss
 
PDF
SpringOne Platform recap 정윤진
VMware Tanzu Korea
 
PDF
Introduction to Cloud Foundry #JJUG
Toshiaki Maki
 
PPTX
Spring Cloud Netflixを使おう #jsug
Toshiaki Maki
 
PDF
Spring Boot Actuator 2.0 & Micrometer
Toshiaki Maki
 
PPTX
Building Web Apps in Ratpack
Daniel Woods
 
Short Lived Tasks in Cloud Foundry #cfdtokyo
Toshiaki Maki
 
Why PCF is the best platform for Spring Boot
Toshiaki Maki
 
Spring Framework 5.0による Reactive Web Application #JavaDayTokyo
Toshiaki Maki
 
Introduction to Concourse CI #渋谷Java
Toshiaki Maki
 
Event Driven Microservices with Spring Cloud Stream #jjug_ccc #ccc_ab3
Toshiaki Maki
 
Microservices with Spring and Cloud Foundry
Alain Sahli
 
From Spring Boot 2.2 to Spring Boot 2.3 #jsug
Toshiaki Maki
 
Introduction to Spring WebFlux #jsug #sf_a1
Toshiaki Maki
 
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
Toshiaki Maki
 
マイクロサービスに必要な技術要素はすべてSpring Cloudにある #DO07
Toshiaki Maki
 
今すぐ始めるCloud Foundry #hackt #hackt_k
Toshiaki Maki
 
クラウド時代の Spring Framework (aka Spring Framework in Cloud Era)
Tsuyoshi Miyake
 
Spring5 New Features - Nov, 2017
VMware Tanzu Korea
 
Serverless with Spring Cloud Function, Knative and riff #SpringOneTour #s1t
Toshiaki Maki
 
Spring Cloud Stream with Kafka
David Kiss
 
SpringOne Platform recap 정윤진
VMware Tanzu Korea
 
Introduction to Cloud Foundry #JJUG
Toshiaki Maki
 
Spring Cloud Netflixを使おう #jsug
Toshiaki Maki
 
Spring Boot Actuator 2.0 & Micrometer
Toshiaki Maki
 
Building Web Apps in Ratpack
Daniel Woods
 

Similar to Spring ❤️ Kotlin #jjug (20)

PDF
How to Architect and Develop Cloud Native Applications
Sufyaan Kazi
 
PPTX
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
mfrancis
 
PDF
Bytecode Verification, the Hero That Java Needs [JavaOne 2016 CON1500]
David Buck
 
PPTX
What's new in the Java API for JSON Binding
Dmitry Kornilov
 
PDF
Leveraging the Latest OSGi R7 Specifications - C Ziegeler & D Bosschaert
mfrancis
 
PPTX
Best practices iOS meetup - pmd
Suyash Gupta
 
PPTX
Configuration for Java EE and the Cloud
Dmitry Kornilov
 
PDF
Declaring Server App Components in Pure Java
Atlassian
 
PDF
Leverage integration cloud_service_for_ebs_
aioughydchapter
 
PPTX
Interactive Java Support to your tool -- The JShell API and Architecture
JavaDayUA
 
PDF
Jaroslav Tulach: GraalVM - z vývoje nejrychlejšího virtuálního stroje na světě
Develcz
 
PDF
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
C4Media
 
PDF
All You Need is Structure
LavaCon
 
PDF
IMMERSE'16 Introduction to adobe experience manager back end
AdobeMarketingCloud
 
PDF
Manchester geek night pcf 101
Sufyaan Kazi
 
PDF
Leveraging Open Source for Database Development: Database Version Control wit...
All Things Open
 
PDF
Swift 2.2 Design Patterns CocoaConf Austin 2016
Carl Brown
 
PDF
Unleashing the Power of Automated Refactoring with JDT
Naresh Jain
 
PDF
Compose Camp Session 1.pdf
AbhishekRajoraB20CS0
 
PPTX
Using Spring with Scala
BernhardWenzel
 
How to Architect and Develop Cloud Native Applications
Sufyaan Kazi
 
New and cool in OSGi R7 - David Bosschaert & Carsten Ziegeler
mfrancis
 
Bytecode Verification, the Hero That Java Needs [JavaOne 2016 CON1500]
David Buck
 
What's new in the Java API for JSON Binding
Dmitry Kornilov
 
Leveraging the Latest OSGi R7 Specifications - C Ziegeler & D Bosschaert
mfrancis
 
Best practices iOS meetup - pmd
Suyash Gupta
 
Configuration for Java EE and the Cloud
Dmitry Kornilov
 
Declaring Server App Components in Pure Java
Atlassian
 
Leverage integration cloud_service_for_ebs_
aioughydchapter
 
Interactive Java Support to your tool -- The JShell API and Architecture
JavaDayUA
 
Jaroslav Tulach: GraalVM - z vývoje nejrychlejšího virtuálního stroje na světě
Develcz
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
C4Media
 
All You Need is Structure
LavaCon
 
IMMERSE'16 Introduction to adobe experience manager back end
AdobeMarketingCloud
 
Manchester geek night pcf 101
Sufyaan Kazi
 
Leveraging Open Source for Database Development: Database Version Control wit...
All Things Open
 
Swift 2.2 Design Patterns CocoaConf Austin 2016
Carl Brown
 
Unleashing the Power of Automated Refactoring with JDT
Naresh Jain
 
Compose Camp Session 1.pdf
AbhishekRajoraB20CS0
 
Using Spring with Scala
BernhardWenzel
 
Ad

More from Toshiaki Maki (10)

PDF
決済システムの内製化への旅 - SpringとPCFで作るクラウドネイティブなシステム開発 #jsug #sf_h1
Toshiaki Maki
 
PDF
Spring Boot Actuator 2.0 & Micrometer #jjug_ccc #ccc_a1
Toshiaki Maki
 
PDF
Open Service Broker APIとKubernetes Service Catalog #k8sjp
Toshiaki Maki
 
PDF
BOSH / CF Deployment in modern ways #cf_tokyo
Toshiaki Maki
 
PDF
Zipkin Components #zipkin_jp
Toshiaki Maki
 
PDF
Data Microservices with Spring Cloud Stream, Task, and Data Flow #jsug #spri...
Toshiaki Maki
 
PDF
Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech
Toshiaki Maki
 
PDF
Implement Service Broker with Spring Boot #cf_tokyo
Toshiaki Maki
 
PDF
Concourse CI Meetup Demo
Toshiaki Maki
 
PDF
Install Concourse CI with BOSH
Toshiaki Maki
 
決済システムの内製化への旅 - SpringとPCFで作るクラウドネイティブなシステム開発 #jsug #sf_h1
Toshiaki Maki
 
Spring Boot Actuator 2.0 & Micrometer #jjug_ccc #ccc_a1
Toshiaki Maki
 
Open Service Broker APIとKubernetes Service Catalog #k8sjp
Toshiaki Maki
 
BOSH / CF Deployment in modern ways #cf_tokyo
Toshiaki Maki
 
Zipkin Components #zipkin_jp
Toshiaki Maki
 
Data Microservices with Spring Cloud Stream, Task, and Data Flow #jsug #spri...
Toshiaki Maki
 
Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech
Toshiaki Maki
 
Implement Service Broker with Spring Boot #cf_tokyo
Toshiaki Maki
 
Concourse CI Meetup Demo
Toshiaki Maki
 
Install Concourse CI with BOSH
Toshiaki Maki
 
Ad

Recently uploaded (20)

PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PPTX
Designing Production-Ready AI Agents
Kunal Rai
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Biography of Daniel Podor.pdf
Daniel Podor
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
Designing Production-Ready AI Agents
Kunal Rai
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 

Spring ❤️ Kotlin #jjug

  • 1. ‹#›© 2016 Pivotal Software, Inc. All rights reserved. ‹#›© 2016 Pivotal Software, Inc. All rights reserved. Spring ❤ Kotlin Toshiaki Maki (@making) [email protected] JJUG Night Seminar 2017 Feb 2017-02-20
  • 2. © 2016 Pivotal Software, Inc. All rights reserved. Who am I ? • Toshiaki Maki (@making) https://ik.am • Sr. Solutions Architect @Pivotal • Spring ☘ / Cloud Foundry ☁ / Concourse ✈ / BOSH 🐚 bit.ly/hajiboot2
  • 3. © 2016 Pivotal Software, Inc. All rights reserved. Agenda •Spring Boot with Kotlin •Kotlin support in Spring 5
  • 4. ‹#›© 2016 Pivotal Software, Inc. All rights reserved. Spring Boot with Kotlin
  • 5. © 2016 Pivotal Software, Inc. All rights reserved. Spring Initializr
  • 6. © 2016 Pivotal Software, Inc. All rights reserved. Spring Initializr
  • 7. © 2016 Pivotal Software, Inc. All rights reserved.
  • 8. © 2016 Pivotal Software, Inc. All rights reserved.
  • 9. © 2016 Pivotal Software, Inc. All rights reserved.
  • 10. © 2016 Pivotal Software, Inc. All rights reserved.
  • 11. © 2016 Pivotal Software, Inc. All rights reserved.
  • 12. © 2016 Pivotal Software, Inc. All rights reserved.
  • 13. © 2016 Pivotal Software, Inc. All rights reserved.
  • 14. © 2016 Pivotal Software, Inc. All rights reserved. package com.example
 
 import org.springframework.boot.SpringApplication
 import org.springframework.boot.autoconfigure.SpringBootApplication
 
 @SpringBootApplication
 class DemoApplication
 
 fun main(args: Array<String>) {
 SpringApplication.run(DemoApplication::class.java, *args)
 }

  • 15. © 2016 Pivotal Software, Inc. All rights reserved.
  • 16. © 2016 Pivotal Software, Inc. All rights reserved. package com.example
 
 import org.springframework.web.bind.annotation.GetMapping
 import org.springframework.web.bind.annotation.RestController
 
 @RestController
 class HelloController {
 @GetMapping("/")
 fun hello() = "Hello World!"
 } 

  • 17. © 2016 Pivotal Software, Inc. All rights reserved. package com.example
 
 import org.springframework.web.bind.annotation.GetMapping
 import org.springframework.web.bind.annotation.RestController
 
 @RestController
 class HelloController {
 @GetMapping("/")
 fun hello() = "Hello World!"
 } 

  • 18. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin open class AppConfig {
 @Bean
 open fun restTemplate() = RestTemplate()
 }
  • 19. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin open class AppConfig {
 @Bean
 open fun restTemplate() = RestTemplate()
 } 👇 👇
  • 20. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin open class AppConfig {
 @Bean
 open fun restTemplate() = RestTemplate()
 } 👇 👇 😩
  • 21. © 2016 Pivotal Software, Inc. All rights reserved. Cglib and Spring // Java class AppConfig {
 @Bean
 RestTemplate restTemplate() { return new RestTemplate(); }
 }
  • 22. © 2016 Pivotal Software, Inc. All rights reserved. Cglib and Spring // Java class AppConfig {
 @Bean
 RestTemplate restTemplate() { return new RestTemplate(); }
 } Singleton
  • 23. © 2016 Pivotal Software, Inc. All rights reserved. Cglib and Spring (Pseudo Code) class AppConfig$$ extends AppConfig { @Override
 RestTemplate restTemplate() { if (context.contains("restTemplate")) { return context.get("restTemplate"); } return super.restTemplate(); }
 }
  • 24. © 2016 Pivotal Software, Inc. All rights reserved. Cglib and Spring (Pseudo Code) class AppConfig$$ extends AppConfig { @Override
 RestTemplate restTemplate() { if (context.contains("restTemplate")) { return context.get("restTemplate"); } return super.restTemplate(); }
 } Methods in Kotlin are final by default !! open removes final
  • 25. © 2016 Pivotal Software, Inc. All rights reserved. <plugin>
 <artifactId>kotlin-maven-plugin</artifactId>
 <groupId>org.jetbrains.kotlin</groupId>
 <version>${kotlin.version}</version>
 <configuration>
 <compilerPlugins>
 <plugin>spring</plugin>
 </compilerPlugins>
 </configuration> </plugin>
  • 26. © 2016 Pivotal Software, Inc. All rights reserved. open class AppConfig {
 @Bean
 open fun restTemplate() = RestTemplate()
 }
  • 27. © 2016 Pivotal Software, Inc. All rights reserved. open class AppConfig {
 @Bean
 open fun restTemplate() = RestTemplate()
 }
  • 28. © 2016 Pivotal Software, Inc. All rights reserved. class AppConfig {
 @Bean
 fun restTemplate() = RestTemplate()
 }
  • 29. © 2016 Pivotal Software, Inc. All rights reserved. class AppConfig {
 @Bean
 fun restTemplate() = RestTemplate()
 } 😍
  • 30. © 2016 Pivotal Software, Inc. All rights reserved. http://start.spring.io/#!language=kotlin
  • 31. ‹#›© 2016 Pivotal Software, Inc. All rights reserved. Kotlin support in Spring 5
  • 32. © 2016 Pivotal Software, Inc. All rights reserved. Spring Framework 5 •Java 8 baseline, Java 9 compatibility •Reactive Support & Spring WebFlux •Router Functions •Performance improvements •HTTP/2 support •Kotlin support
  • 33. © 2016 Pivotal Software, Inc. All rights reserved. Kotlin Support
  • 34. © 2016 Pivotal Software, Inc. All rights reserved. Kotlin Support
  • 35. © 2016 Pivotal Software, Inc. All rights reserved. Kotlin Support •Extension Functions •Reified type parameters
  • 36. © 2016 Pivotal Software, Inc. All rights reserved. Kotlin Support •Extension Functions •Reified type parameters 🤔
  • 37. © 2016 Pivotal Software, Inc. All rights reserved. package com.example; public class Foo { public <T> T create(Class<T> clazz) { try { return clazz.newInstance(); } catch (Exception e) { throw new IllegalStateException(e); } } }
  • 38. © 2016 Pivotal Software, Inc. All rights reserved. // Java Foo foo = new Foo(); Bar bar = foo.create(Bar.class);
  • 39. © 2016 Pivotal Software, Inc. All rights reserved. // Java Foo foo = new Foo(); Bar bar = foo.create(Bar.class); // Kotlin val foo = Foo() val bar = foo.create(Bar::class.java)
  • 40. © 2016 Pivotal Software, Inc. All rights reserved. // Java Foo foo = new Foo(); Bar bar = foo.create(Bar.class); // Kotlin val foo = Foo() val bar = foo.create(Bar::class.java) 👇
  • 41. © 2016 Pivotal Software, Inc. All rights reserved. KClass Bar::class // kotlin.reflect.KClass Bar::class.java // java.lang.Class

  • 42. © 2016 Pivotal Software, Inc. All rights reserved. Extension Functions •Extends a class with new functionality without having to inherit from the class •https://kotlinlang.org/docs/reference/ extensions.html#extension-functions
  • 43. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin val foo = Foo() val bar = foo.create(Bar::class.java)
  • 44. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin val foo = Foo() val bar = foo.create(Bar::class.java)
  • 45. © 2016 Pivotal Software, Inc. All rights reserved. // Kotlin val foo = Foo() val bar = foo.create(Bar::class)
  • 46. © 2016 Pivotal Software, Inc. All rights reserved. Extension Functions // Kotlin val foo = Foo() val bar = foo.create(Bar::class)
  • 47. © 2016 Pivotal Software, Inc. All rights reserved. Extension Functions package com.example import kotlin.reflect.KClass fun <T : Any> Foo.create(kclass: KClass<T>) = create(kclass.java)
 FooExtensions.kt
  • 48. © 2016 Pivotal Software, Inc. All rights reserved. Extension Functions package com.example import kotlin.reflect.KClass fun <T : Any> Foo.create(kclass: KClass<T>) = create(kclass.java)
 👇 FooExtensions.kt
  • 49. © 2016 Pivotal Software, Inc. All rights reserved. Extension Functions // Kotlin val foo = Foo() val bar = foo.create(Bar::class) 😍
  • 50. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters •Access a type passed to us as a parameter •https://kotlinlang.org/docs/reference/inline- functions.html#reified-type-parameters
  • 51. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters inline fun <reified T : Any> Foo.create() = create(T::class.java)

  • 52. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters inline fun <reified T : Any> Foo.create() = create(T::class.java)
👇 👇
  • 53. © 2016 Pivotal Software, Inc. All rights reserved. val foo = Foo() val bar = foo.create(Bar::class)

  • 54. © 2016 Pivotal Software, Inc. All rights reserved. val foo = Foo() val bar = foo.create(Bar::class)

  • 55. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters val foo = Foo() val bar = foo.create<Bar>()
 😍
  • 56. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters val foo = Foo() val bar: Bar = foo.create()
 😍
  • 57. © 2016 Pivotal Software, Inc. All rights reserved. Reified type parameters val foo = Foo() val bar: Bar = foo.create()
 😍 "idiomatic Kotlin code"
  • 58. © 2016 Pivotal Software, Inc. All rights reserved. "idiomatic Kotlin code" with Spring 5
  • 59. © 2016 Pivotal Software, Inc. All rights reserved. Application Context // Java ApplicationContext context = ...; Bar bar = context.getBean(Bar.class);
  • 60. © 2016 Pivotal Software, Inc. All rights reserved. Application Context (Extension) // Kotlin val context = ... val bar = context.getBean(Bar::class)

  • 61. © 2016 Pivotal Software, Inc. All rights reserved. Application Context (Reified Type) // Kotlin val context = ... val bar = context.getBean<Bar>()

  • 62. © 2016 Pivotal Software, Inc. All rights reserved. Application Context (Reified Type) // Kotlin val context = ... val bar: Bar = context.getBean()

  • 63. © 2016 Pivotal Software, Inc. All rights reserved. JdbcTemplate // Java Long count = jdbcTemplate .queryForObject("SELECT count(*) FROM foo" , Long.class);
  • 64. © 2016 Pivotal Software, Inc. All rights reserved. JdbcTemplate (Extension) // Kotlin val count = jdbcTemplate .queryForObject("SELECT count(*) FROM foo" , Long::class)
  • 65. © 2016 Pivotal Software, Inc. All rights reserved. JdbcTemplate (Reified Type) // Kotlin val count = jdbcTemplate .queryForObject<Long>( "SELECT count(*) FROM foo")
  • 66. © 2016 Pivotal Software, Inc. All rights reserved. JdbcTemplate (Reified Type) // Kotlin val count: Long = jdbcTemplate .queryForObject("SELECT count(*) FROM foo")
  • 67. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate // Java String foo = restTemplate .getForObject("http://abc.io",String.class);
  • 68. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate (Reified Type) // Kotlin val foo = restTemplate .getForObject<String>("http://abc.io");
  • 69. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate (Reified Type) // Kotlin val foo: String = restTemplate .getForObject("http://abc.io");
  • 70. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate // Java List<Foo> foos = restTemplate .getForObject("http://abc.io", List<Foo>.class);
  • 71. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate // Java List<Foo> foos = restTemplate .getForObject("http://abc.io", List<Foo>.class); Compile Error!
  • 72. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate // Java List<Foo> foos = restTemplate .exchange("http://abc.io", HttpMethod.GET, null, new ParameterizedTypeReference<List<Foo>>() {}).getBody();
  • 73. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate // Java List<Foo> foos = restTemplate .exchange("http://abc.io", HttpMethod.GET, null, new ParameterizedTypeReference<List<Foo>>() {}).getBody(); 💩
  • 74. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate (Reified Type)
  • 75. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate (Reified Type) // Kotlin val foos: List<Foo> = restTemplate .getForObject("http://abc.io");
  • 76. © 2016 Pivotal Software, Inc. All rights reserved. RestTemplate (Reified Type) // Kotlin val foos: List<Foo> = restTemplate .getForObject("http://abc.io"); 😍
  • 77. © 2016 Pivotal Software, Inc. All rights reserved. Spring ❤ Kotlin
  • 78. © 2016 Pivotal Software, Inc. All rights reserved. Spring Framework 5 •Java 8 baseline, Java 9 compatibility •Reactive Support & Spring WebFlux •Router Functions •Performance improvements •HTTP/2 support •Kotlin support
  • 79. © 2016 Pivotal Software, Inc. All rights reserved. Spring Framework 5 •Java 8 baseline, Java 9 compatibility •Reactive Support & Spring WebFlux •Router Functions •Performance improvements •HTTP/2 support •Kotlin support 👇 👇
  • 80. © 2016 Pivotal Software, Inc. All rights reserved. Spring Framework 5 •Java 8 baseline, Java 9 compatibility •Reactive Support & Spring WebFlux •Router Functions •Performance improvements •HTTP/2 support •Kotlin support 👇 👇 🤔
  • 81. © 2016 Pivotal Software, Inc. All rights reserved.
  • 82. © 2016 Pivotal Software, Inc. All rights reserved. WebMVC + @Controller in Java @RestController public class UserController { private final UserRepository repo; UserController(UserRepository repo) {/.../} @GetMapping List<User> users() { return repo.findAll(); } }
  • 83. © 2016 Pivotal Software, Inc. All rights reserved. WebFlux + @Controller in Java @RestController public class UserController { private final ReactiveUserRepository repo; UserController(ReactiveUserRepository repo) {/.../} @GetMapping Flux<User> users() { return repo.findAll(); } }
  • 84. © 2016 Pivotal Software, Inc. All rights reserved. WebFlux + @Controller in Java @RestController public class UserController { private final ReactiveUserRepository repo; UserController(ReactiveUserRepository repo) {/.../} @GetMapping Flux<User> users() { return repo.findAll(); } } Non-Blocking!!
  • 85. © 2016 Pivotal Software, Inc. All rights reserved. WebFlux + RouterFunction in Java
  • 86. © 2016 Pivotal Software, Inc. All rights reserved. WebFlux + RouterFunction in Java RouterFunction<?> routes = route(GET("/users"), req -> ok() .body(repo.findAll(), User.class));
  • 87. © 2016 Pivotal Software, Inc. All rights reserved. WebFlux + RouterFunction in Kotlin { accept(APPLICATION_JSON).apply { GET("/users",{ ok().body(fromPublisher(repo.findAll()) }) } }
  • 88. © 2016 Pivotal Software, Inc. All rights reserved. Check source code!! • https://github.com/mix-it/mixit • https://github.com/making/demo-router-functions
  • 89. © 2016 Pivotal Software, Inc. All rights reserved. Other Kotlin Support •Functional Bean Registration with Kotlin •WebFlux functional API, the Kotlin way •Leveraging Kotlin nullable information •Kotlin Script based templates •... •https://speakerdeck.com/sdeleuze/functional- web-applications-with-kotlin-and-spring-5?
  • 90. © 2016 Pivotal Software, Inc. All rights reserved. Release date https://jira.spring.io/browse/SPR
  • 91. © 2016 Pivotal Software, Inc. All rights reserved. http://start.spring.io/#!language=kotlin
  • 92. © 2016 Pivotal Software, Inc. All rights reserved. http://start.spring.io/#!language=kotlin
  • 93. © 2016 Pivotal Software, Inc. All rights reserved. http://start.spring.io/#!language=kotlin
  • 94. © 2016 Pivotal Software, Inc. All rights reserved. http://start.spring.io/#!language=kotlin
  • 95. © 2016 Pivotal Software, Inc. All rights reserved. Resources • https://spring.io/blog/2017/01/04/introducing-kotlin-support- in-spring-framework-5-0 • https://speakerdeck.com/sdeleuze • https://blog.ik.am/entries/407
  • 96. © 2016 Pivotal Software, Inc. All rights reserved. CfP for JJUG CCC 2017 Spring •Submit Call for Paper!!! 🙇 •http://www.java-users.jp/?p=2830