SlideShare a Scribd company logo
1 of 80
Download to read offline
otlin
Serverless
(Shengyou Fan)
JCConf 2020
2020/11/19
Photo by Cam Adams on Unsplash
—
• Serverless
• FaaS Kotlin
• Kotless
•
—
Develop Build/Pack Deploy Scale Up
Operation …
!
Kotlin
Serverless
—
from Wikipedia
Serverless computing is a cloud computing execution
model in which the cloud provider runs the server,
and dynamically manages the allocation of machine
resources.
Serverless
—
Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
Serverless
—
•
•
•
•
FaaS Java
—
Kotlin
"
Kotlin
—
?query=param
①
②
③
④
Client
FaaS
Local Development
Kotlin Functions
HTTP Request
—
GET http://localhost:8001/?amount={n}
Accept: application/json
1. n Contact
2. JSON
HTTP Response
—
{
"data": [
{
"id": ...,
"name": "...",
"email": "...",
"createdAt": "yyyy-MM-dd HH:mm:ss.nnnnnn",
"updatedAt": "yyyy-MM-dd HH:mm:ss.nnnnnn"
},
// ...
]
}
1. n
2. JSON
3. data
Data Class
—
// Data Class
data class Contact(
val id: Long?,
val name: String,
val email: String,
val createdAt: String,
val updatedAt: String
)
// JSON
{
"id": 1,
"name": "...",
"email": "...",
"createdAt": "yyyy-MM-dd HH:mm:ss.nnnnnn",
"updatedAt": "yyyy-MM-dd HH:mm:ss.nnnnnn"
}
• JSON Data Class
class ContactService() {
// ...
@ExperimentalTime
fun generate(amount: Int = 10): List<Contact> {
return (1..amount).map {
Contact(
// ...
)
}
}
}
Service Class
—
Service
• javafaker datetime
serilization library
•
•
JetBrains Package Search
—
Packages Tool Window
—
Lorem ipsum dolor sit amet, ad nam alterum copiosae facilisis, ad vis detracto vituperata, an
errem oblique discere qui. Vim noster dolorem legendos no. Cu lorem dicta docendi mei, has
an causae facilis abhorreant. Ex ornatus similique eum, et diam regione consetetur vix. Mea
id paulo vituperata, nam laoreet luptatum delicatissimi id. Fugit primis ullamcorper no qui,
nusquam accusamus temporibus sit ad.
Vis iudico commodo ne, ad eam quas legimus, esse dicant explicari has in. Eum ocurreret
interesset appellantur ei, quo cu timeam euismod laoreet. Per ne nisl justo. An vel laboramus
efficiantur deterruisset, nec ne mandamus scripserit, vix id rebum dicta dictas. Mel suscipit
periculis similique in.
// build.gradle
dependencies {
implementation "com.github.javafaker:javafaker:1.0.2"
}
// io.kraftsman.services.ContactService
val faker = Faker(Locale("en"))
Contact(
id = it.toLong(),
name = faker.name().fullName(),
email = faker.internet().emailAddress(),
createdAt = ...,
updatedAt = ...
)
Java Faker
—
• Java Faker
• Faker
kotlinx.datetime
• repository
•
// build.gradle
repositories {
maven { url "https://kotlin.bintray.com/kotlinx/" }
}
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-datetime:$ver"
}
// io.kraftsman.services.ContactService
val current = Clock.System.now()
val tz = TimeZone.of("Asia/Taipei")
Contact(
// ...
createdAt = current
.toLocalDateTime(tz).toString(),
updatedAt = (current + x.hours + y.minutes)
.toLocalDateTime(tz).toString()
)
Datetime
—
kotlinx.datetime
•
•
• (x + y )
•
// build.gradle
plugins {
id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.10'
}
repositories {
jcenter()
}
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$ver"
}
• Gradle Plugin
Serialization (pt.1)
—
• Repository
•
// io.kraftsman.dtos.Contact
@Serializable
data class Contact(
// ...
)
// io.kraftsman.functions.Handler
val contacts: List<Contact> = ContactService().generate(amount)
Json.encodeToString(
mapOf("data" to contacts)
)
Serialization (pt.2)
—
• Annotation
JSON
• List Map data
• Map JSON
Cloud Functions
—
• IntelliJ IDEA
• JDK 11
• gcloud CLI
Repository: https://github.com/shengyou/gcp-cloud-functions-kotlin
$ brew cask install google-cloud-sdk
$ gcloud auth login
$ gcloud projects list
$ gcloud config set project PROJECT_ID
/ gcloud
—
• gcloud CLI
• GCP
• GCP Project
• GCP Project
1. Kotlin
2. Gradle
3. JDK 11
—
configurations {
invoker
}
dependencies {
implementation "...:functions-framework-api:$ver"
invoker "...:java-function-invoker:$ver"
}
tasks.register("runFunction", JavaExec) {
main = '...'
classpath(configurations.invoker)
inputs.files(..., ...)
args(
'--target', ...Property('runFunction.target') ?: '',
'--port', ...Property('runFunction.port') ?: ...
)
doFirst {
args('--classpath', ...)
}
}
Gradle
—
Cloud Function
• functions-framework-api
• java-function-invoker
Gradle Task
$ gradle runFunction
Java Invoker
class Handler: HttpFunction {
@Throws(IOException::class)
override fun service(req: HttpRequest, res: HttpResponse) {
}
}
Handler
—
• Class
• HttpFunction (
functions-framework-api)
• service()
• req res
class Handler: HttpFunction {
@Throws(IOException::class)
override fun service(req: HttpRequest, res: HttpResponse) {
val param = request.getFirstQueryParameter("amount")
.orElse("")
val amount = param.toIntOrNull() ?: 10
}
}
Query
—
• HttpRequest Query
•
class Handler: HttpFunction {
@Throws(IOException::class)
override fun service(req: HttpRequest, res: HttpResponse) {
val param = request.getFirstQueryParameter("amount")
.orElse("")
val amount = param.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
}
}
/
—
• Service
• JSON
class Handler: HttpFunction {
@Throws(IOException::class)
override fun service(req: HttpRequest, res: HttpResponse) {
val param = request.getFirstQueryParameter("amount")
.orElse("")
val amount = param.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
with(res) {
setStatusCode(HttpURLConnection.HTTP_OK)
setContentType("application/json")
writer.write(jsonString)
}
}
}
Response
—
• HTTP Status Code
• Content-Type
• JSON
$ ./gradlew runFunction 
-PrunFunction.target=CLASS 
-PrunFunction.port=PORT
—
• Gradle Task
• Run Configuration
$ gcloud functions deploy PUBLIC_PATH 
--region REGION 
--runtime java11 
--trigger-http 
--memory 256MB 
--entry-point ENTRY_POINT_CLASS 
--allow-unauthenticated
—
• gcloud
Azure Functions
—
• IntelliJ IDEA + Plugins
• JDK 8
• Azure CLI
• Azure Functions Core Tools
Repository: https://github.com/shengyou/microsoft-azure-functions-kotlin
$ brew update
$ brew install azure-cli
$ az login
$ az account -a SUBSCRIPTION_ID
$ brew tap azure/functions
$ brew installazure-function-core-tools@3
—
• Azure CLI
• Azure
• Azure Functions Core Tools
• Azure Toolkit for IntelliJ
1. Azure Functions
2. Gradle
3. JDK 8
—
1. Azure Functions
2. Gradle
3. JDK 8
Kotlin
— ①
②
③
④
1. Project
2. Class
3.
Kotlin Class
—
class Handler {
@FunctionName("...")
fun run(
@HttpTrigger(
name = "...",
route = "...",
methods = [HttpMethod.GET],
authLevel = AuthorizationLevel.ANONYMOUS
)
request: HttpRequestMessage<Optional<String?>>,
context: ExecutionContext
): HttpResponseMessage {
// ...
}
}
Handler
—
• Class Method
• Annotation
• route methods
• request context
class Handler {
@FunctionName("...")
fun run(/* . . . */): HttpResponseMessage {
val query = request.queryParameters["amount"]
val amount = query?.toIntOrNull() ?: 10
}
}
Query
—
• request Query
•
class Handler {
@FunctionName("...")
fun run(/* . . . */): HttpResponseMessage {
val query = request.queryParameters["amount"]
val amount = query?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
}
}
/
—
• Service
• JSON
class Handler {
@FunctionName("...")
fun run(/* . . . */): HttpResponseMessage {
val query = request.queryParameters["amount"]
val amount = query?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
return request.createResponseBuilder(HttpStatus.OK)
.header("Content-Type", "application/json")
.body(jsonString)
.build()
}
}
Response
—
• HTTP Status Code
• Content-Type
• JSON
—
• Gradle Task
azurefunctions {
subscription = '...'
resourceGroup = '...'
appName = '...'
pricingTier = 'Consumption'
region = '...'
runtime {
os = 'linux'
}
authentication {
type = 'azure_cli'
}
}
—
• Azure Gradle
• Gradle Task
AWS Lambda
—
• IntelliJ IDEA + Plugin
• JDK 11
• Docker
• AWS CLI
• AWS SAM CLI
Repository: https://github.com/shengyou/amazon-lambda-kotlin
$ brew update
$ brew install awscli
$ aws configure
$ aws sts get-caller-identity
$ brew tap aws/tap
$ brew install aws-sam-cli
—
• AWS CLI
• AWS
• Account ID
• IAM (User & Role)
• AWS SAM CLI
• AWS Toolkit
1. Kotlin
2. Gradle
3. JDK 11
—
1. AWS
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '6.1.0'
}
dependencies {
implementation "...:aws-lambda-java-core:1.2.1"
implementation "...:aws-lambda-java-events:3.1.0"
runtimeOnly "...:aws-lambda-java-log4j2:1.2.0"
}
Gradle
—
AWS Lambda
• aws-lambda-java-core
• aws-lambda-java-events
• aws-lambda-java-log4j2
Gradle Plugin
• java
• shadow
class Handler : RequestHandler <
APIGatewayProxyRequestEvent,
APIGatewayProxyResponseEvent
> {
@Throws(IOException::class)
override fun handleRequest(
request: APIGatewayProxyRequestEvent,
context: Context
): APIGatewayProxyResponseEvent {
// ...
}
}
Handler
—
• Class Method
• RequestHandler ( aws-
lambda-java-core)
• Handler Method
• reqest context
class Handler : RequestHandler <...> {
@Throws(IOException::class)
override fun method(/* ... */): ...ResponseEvent {
val param = request.queryStringParameters["amount"]
val amount = param?.toIntOrNull() ?: 10
}
}
Query
—
• request Query
•
class Handler : RequestHandler <...> {
@Throws(IOException::class)
override fun method(/* ... */): ...ResponseEvent {
val param = request.queryStringParameters["amount"]
val amount = param?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
}
}
/
—
• Service
• JSON
class Handler : RequestHandler <...> {
@Throws(IOException::class)
override fun method(/* ... */): ...ResponseEvent {
val param = request.queryStringParameters["amount"]
val amount = param?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val jsonString = Json.encodeToString(
mapOf("data" to contacts)
)
return APIGatewayProxyResponseEvent()
.withStatusCode(HttpURLConnection.HTTP_OK)
.withHeaders(
mapOf("Content-Type" to "application/json")
)
.withBody(jsonString)
}
}
Response
—
• HTTP Status Code
• Content-Type
• JSON
$ aws lambda create-function --function-name NAME 
--zip-file fileb://build/libs/SHADOWJAR.jar 
--handler CLASS::METHOD 
--runtime java11
--timeout 15
--memory-size 128
--role ROLE
—
• aws
• AWS Console
API Gateway
—
• Trigger
JDK 11 8 11
IntelliJ Plugin ✗ ✓ ✓
Gradle ✓ ✓
Framework ✓ ✓ ✓
+
—
#
…
Cloud Configuration
Vendor Lock-in…
Kotless
—
https://site.kotless.io/
• Serverless Framework
• Kotless DSL
• Gradle Plugin
• Developed by Vladislav Tankov
from JetBrains
• Open Source (Apache 2.0)
—
Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
1. Kotlin
2. Gradle Kotlin ❤
3. JDK 11
—
plugins {
kotlin("jvm") version "1.3.72" apply true
kotlin("plugin.serialization") version "1.3.72"
id("io.kotless") version "0.1.6" apply true
}
dependencies {
implementation("io.kotless", "kotless-lang", "0.1.6")
}
Gradle
—
Gradle Plugins
• Kotlin 1.3.72
• Serialization 1.3.72
• Kotless 0.1.6
• Kotless
@Get("/")
fun handler(): HttpResponse {
val dom = """
// ...
""".trimIndent()
return html(dom)
}
Function
—
• Function
• Annotation Route
• HttpResponse
@Get("/...")
fun handler(): HttpResponse {
val param = KotlessContext.HTTP.request.params?.get("amount")
val amount = param?.toIntOrNull() ?: 10
}
Query
—
• KotlessContext Query
•
@Get("/...")
fun handler(): HttpResponse {
val param = KotlessContext.HTTP.request.params?.get("amount")
val amount = param?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val json = Json(JsonConfiguration.Stable)
val jsonString = json.stringify(
Contact.serializer(), contacts
)
}
/
—
• Service
• JSON
@Get("/...")
fun handler(): HttpResponse {
val param = KotlessContext.HTTP.request.params?.get("amount")
val amount = param?.toIntOrNull() ?: 10
val contacts = ContactService().generate(amount)
val json = Json(JsonConfiguration.Stable)
val jsonString = json.stringify(
Contact.serializer(), contacts
)
return json(jsonString)
}
Response
—
• JSON
—
• Gradle Task
kotless {
config {
bucket = "..."
terraform {
profile = "..."
region = "..."
}
}
}
—
• AWS CLI Credentials
• S3 Bucket
• AWS Gradle
• Gradle Task
#
…
Serverless
Kotless
—
Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
1. Ktor (1.3.2)
2. Gradle Kotlin ❤
3. JDK 11
4. Server Features
• Routing
• ContentNegotiation
• Jackson
Ktor
—
plugins {
id("io.kotless") version "0.1.6" apply true
}
dependencies {
// ...
implementation("io.ktor:ktor-server-netty:$ktor_version")
// ...
implementation("io.kotless", "ktor-lang", “0.1.6")
// ...
}
Gradle
—
Gradle Plugins
• Kotless 0.1.6
• Netty
• Kotless for Ktor
class Server : Kotless() {
override fun prepare(app: Application) {
app.install(ContentNegotiation) {
jackson {
enable(SerializationFeature.INDENT_OUTPUT)
}
}
app.routing {
// ...
}
}
}
Kotless App
—
Kotless App
• Kotless
• prepare()
• Ktor app
// Application.kt
@Suppress("unused")
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
// ...
}
// resources/application.conf
ktor {
deployment {
port = 8080
port = ${?PORT}
}
application {
modules = [ io.kraftsman.Server.prepare ]
}
}
—
• Application.kt
•
Roadmap
—
Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
% & %
Repository: https://github.com/shengyou/jetbrains-kotless-framework
Repository: https://github.com/shengyou/jetbrains-ktor-with-kotless
—
• Serverless
• Kotlin Serverless
• Kotless Framework
• Kotless
Serverless
—
• IBM Bluemix
• Cloudflare Workers
• Alibaba Cloud
• Huawei Cloud
• …
Serverless
—
• Fat Jar
• Container
• Kotlin/JS
Serverless
—
• Spring Cloud Function
• Micronaut
• Osiris
• Nimbus
• …
—
• Mobile Backend (API …)
• Webhook ( API …)
• ( …)
—
•
•
•
•
Image source: The Definition of Framework by Francesco Strazzullo
https://tw.kotlin.tips
Tips
—
https://tw.intellij.tips
—
Coding
Kraftsman
(Shengyou Fan)
shengyou.fan@jetbrains.com
Q&A
—
otlin
Serverless

More Related Content

What's hot

Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
Smart Sheriff, Dumb Idea, the wild west of government assisted parentingSmart Sheriff, Dumb Idea, the wild west of government assisted parenting
Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
Abraham Aranguren
 

What's hot (20)

老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具老派浪漫:用 Kotlin 寫 Command Line 工具
老派浪漫:用 Kotlin 寫 Command Line 工具
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
[GDG Kaohsiung DevFest 2023] 以 Compose 及 Kotlin Multiplatform 打造多平台應用程式
 
XXE Exposed: SQLi, XSS, XXE and XEE against Web Services
XXE Exposed: SQLi, XSS, XXE and XEE against Web ServicesXXE Exposed: SQLi, XSS, XXE and XEE against Web Services
XXE Exposed: SQLi, XSS, XXE and XEE against Web Services
 
Promises, promises, and then observables
Promises, promises, and then observablesPromises, promises, and then observables
Promises, promises, and then observables
 
Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
Smart Sheriff, Dumb Idea, the wild west of government assisted parentingSmart Sheriff, Dumb Idea, the wild west of government assisted parenting
Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
PHP para Adultos: Clean Code e Object Calisthenics
PHP para Adultos: Clean Code e Object CalisthenicsPHP para Adultos: Clean Code e Object Calisthenics
PHP para Adultos: Clean Code e Object Calisthenics
 
第一次用 Vue.js 就愛上 [改]
第一次用 Vue.js 就愛上 [改]第一次用 Vue.js 就愛上 [改]
第一次用 Vue.js 就愛上 [改]
 
Building an Android app with Jetpack Compose and Firebase
Building an Android app with Jetpack Compose and FirebaseBuilding an Android app with Jetpack Compose and Firebase
Building an Android app with Jetpack Compose and Firebase
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
 
Module design pattern i.e. express js
Module design pattern i.e. express jsModule design pattern i.e. express js
Module design pattern i.e. express js
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
Rego Deep Dive
Rego Deep DiveRego Deep Dive
Rego Deep Dive
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin Flows
 
날로 먹는 Django admin 활용
날로 먹는 Django admin 활용날로 먹는 Django admin 활용
날로 먹는 Django admin 활용
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 

Similar to [JCConf 2020] 用 Kotlin 跨入 Serverless 世代

Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
Ismael Celis
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0
SO
 
JSON Schema: Your API's Secret Weapon
JSON Schema: Your API's Secret WeaponJSON Schema: Your API's Secret Weapon
JSON Schema: Your API's Secret Weapon
Pete Gamache
 

Similar to [JCConf 2020] 用 Kotlin 跨入 Serverless 世代 (20)

Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
[HKOSCon 2020] Build an api service using ktor rapidly
[HKOSCon 2020] Build an api service using ktor rapidly[HKOSCon 2020] Build an api service using ktor rapidly
[HKOSCon 2020] Build an api service using ktor rapidly
 
Kotlin 在 Web 方面的应用
Kotlin 在 Web 方面的应用Kotlin 在 Web 方面的应用
Kotlin 在 Web 方面的应用
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
huhu
huhuhuhu
huhu
 
Use Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extensionUse Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extension
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web development
 
RoR vs-nodejs-by-jcskyting
RoR vs-nodejs-by-jcskytingRoR vs-nodejs-by-jcskyting
RoR vs-nodejs-by-jcskyting
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0
 
Yesplan: 10 Years later
Yesplan: 10 Years laterYesplan: 10 Years later
Yesplan: 10 Years later
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.js
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
 
Os Pruett
Os PruettOs Pruett
Os Pruett
 
JSON Schema: Your API's Secret Weapon
JSON Schema: Your API's Secret WeaponJSON Schema: Your API's Secret Weapon
JSON Schema: Your API's Secret Weapon
 
Re:Invent 2018 Database Announcements
Re:Invent 2018 Database AnnouncementsRe:Invent 2018 Database Announcements
Re:Invent 2018 Database Announcements
 
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun..."ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
 
Full stack development with node and NoSQL - All Things Open - October 2017
Full stack development with node and NoSQL - All Things Open - October 2017Full stack development with node and NoSQL - All Things Open - October 2017
Full stack development with node and NoSQL - All Things Open - October 2017
 

More from Shengyou Fan

More from Shengyou Fan (20)

[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
 
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
[WebConf Taiwan 2023] 一份 Zend Engine 外帶!透過 Micro 讓一次打包、多處運行變得可能
 
[Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀
[Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀[Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀
[Effective Kotlin 讀書會] 第八章 Efficient collection processing 導讀
 
Using the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your DatabaseUsing the Exposed SQL Framework to Manage Your Database
Using the Exposed SQL Framework to Manage Your Database
 
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
[COSCUP 2022] 讓黑畫面再次偉大 - 用 PHP 寫 CLI 工具
 
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
簡化 JVM 上雲 - 透過 Azure Spring Cloud 提升開發、發佈及服務監控效率
 
[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南
 
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
 
Composer 經典食譜
Composer 經典食譜Composer 經典食譜
Composer 經典食譜
 
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
[Kotlin Serverless 工作坊] 單元 4 - 實作 RSS Aggregator
 
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
[Kotlin Serverless 工作坊] 單元 3 - 實作 JSON API
 
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
[Kotlin Serverless 工作坊] 單元 2 - 簡介 Kotlin Serverless
 
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
[Kotlin Serverless 工作坊] 單元 1 - 開發環境建置
 
用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手用 Kotlin 打造讀書會小幫手
用 Kotlin 打造讀書會小幫手
 
Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章Kotlin 讀書會第三梯次第一章
Kotlin 讀書會第三梯次第一章
 
用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化用 OPENRNDR 將 Chatbot 訊息視覺化
用 OPENRNDR 將 Chatbot 訊息視覺化
 
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
 
Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法Ktor 部署攻略 - 老派 Fat Jar 大法
Ktor 部署攻略 - 老派 Fat Jar 大法
 
以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile Backend以 Kotlin 快速打造 Mobile Backend
以 Kotlin 快速打造 Mobile Backend
 
Kotlin 一條龍 - 打造全平台應用
Kotlin 一條龍 - 打造全平台應用Kotlin 一條龍 - 打造全平台應用
Kotlin 一條龍 - 打造全平台應用
 

Recently uploaded

Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Monica Sydney
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
gajnagarg
 
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
ydyuyu
 
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
ayvbos
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Monica Sydney
 
一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理
F
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
ydyuyu
 
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girlsRussian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Monica Sydney
 
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
一比一原版田纳西大学毕业证如何办理
一比一原版田纳西大学毕业证如何办理一比一原版田纳西大学毕业证如何办理
一比一原版田纳西大学毕业证如何办理
F
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Monica Sydney
 
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
pxcywzqs
 

Recently uploaded (20)

Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
 
Local Call Girls in Seoni 9332606886 HOT & SEXY Models beautiful and charmin...
Local Call Girls in Seoni  9332606886 HOT & SEXY Models beautiful and charmin...Local Call Girls in Seoni  9332606886 HOT & SEXY Models beautiful and charmin...
Local Call Girls in Seoni 9332606886 HOT & SEXY Models beautiful and charmin...
 
20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf
 
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
 
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
 
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
 
Trump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts SweatshirtTrump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts Sweatshirt
 
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
 
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime BalliaBallia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
 
一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
 
APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53
 
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency""Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
 
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girlsRussian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
 
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
call girls in Anand Vihar (delhi) call me [🔝9953056974🔝] escort service 24X7
 
一比一原版田纳西大学毕业证如何办理
一比一原版田纳西大学毕业证如何办理一比一原版田纳西大学毕业证如何办理
一比一原版田纳西大学毕业证如何办理
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
 
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
 

[JCConf 2020] 用 Kotlin 跨入 Serverless 世代

  • 2. — • Serverless • FaaS Kotlin • Kotless •
  • 5. Serverless — from Wikipedia Serverless computing is a cloud computing execution model in which the cloud provider runs the server, and dynamically manages the allocation of machine resources. Serverless
  • 6. — Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
  • 11. HTTP Request — GET http://localhost:8001/?amount={n} Accept: application/json 1. n Contact 2. JSON
  • 12. HTTP Response — { "data": [ { "id": ..., "name": "...", "email": "...", "createdAt": "yyyy-MM-dd HH:mm:ss.nnnnnn", "updatedAt": "yyyy-MM-dd HH:mm:ss.nnnnnn" }, // ... ] } 1. n 2. JSON 3. data
  • 13. Data Class — // Data Class data class Contact( val id: Long?, val name: String, val email: String, val createdAt: String, val updatedAt: String ) // JSON { "id": 1, "name": "...", "email": "...", "createdAt": "yyyy-MM-dd HH:mm:ss.nnnnnn", "updatedAt": "yyyy-MM-dd HH:mm:ss.nnnnnn" } • JSON Data Class
  • 14. class ContactService() { // ... @ExperimentalTime fun generate(amount: Int = 10): List<Contact> { return (1..amount).map { Contact( // ... ) } } } Service Class — Service • javafaker datetime serilization library • •
  • 16. Packages Tool Window — Lorem ipsum dolor sit amet, ad nam alterum copiosae facilisis, ad vis detracto vituperata, an errem oblique discere qui. Vim noster dolorem legendos no. Cu lorem dicta docendi mei, has an causae facilis abhorreant. Ex ornatus similique eum, et diam regione consetetur vix. Mea id paulo vituperata, nam laoreet luptatum delicatissimi id. Fugit primis ullamcorper no qui, nusquam accusamus temporibus sit ad. Vis iudico commodo ne, ad eam quas legimus, esse dicant explicari has in. Eum ocurreret interesset appellantur ei, quo cu timeam euismod laoreet. Per ne nisl justo. An vel laboramus efficiantur deterruisset, nec ne mandamus scripserit, vix id rebum dicta dictas. Mel suscipit periculis similique in.
  • 17. // build.gradle dependencies { implementation "com.github.javafaker:javafaker:1.0.2" } // io.kraftsman.services.ContactService val faker = Faker(Locale("en")) Contact( id = it.toLong(), name = faker.name().fullName(), email = faker.internet().emailAddress(), createdAt = ..., updatedAt = ... ) Java Faker — • Java Faker • Faker
  • 18. kotlinx.datetime • repository • // build.gradle repositories { maven { url "https://kotlin.bintray.com/kotlinx/" } } dependencies { implementation "org.jetbrains.kotlinx:kotlinx-datetime:$ver" } // io.kraftsman.services.ContactService val current = Clock.System.now() val tz = TimeZone.of("Asia/Taipei") Contact( // ... createdAt = current .toLocalDateTime(tz).toString(), updatedAt = (current + x.hours + y.minutes) .toLocalDateTime(tz).toString() ) Datetime — kotlinx.datetime • • • (x + y ) •
  • 19. // build.gradle plugins { id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.10' } repositories { jcenter() } dependencies { implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$ver" } • Gradle Plugin Serialization (pt.1) — • Repository •
  • 20. // io.kraftsman.dtos.Contact @Serializable data class Contact( // ... ) // io.kraftsman.functions.Handler val contacts: List<Contact> = ContactService().generate(amount) Json.encodeToString( mapOf("data" to contacts) ) Serialization (pt.2) — • Annotation JSON • List Map data • Map JSON
  • 21. Cloud Functions — • IntelliJ IDEA • JDK 11 • gcloud CLI Repository: https://github.com/shengyou/gcp-cloud-functions-kotlin
  • 22. $ brew cask install google-cloud-sdk $ gcloud auth login $ gcloud projects list $ gcloud config set project PROJECT_ID / gcloud — • gcloud CLI • GCP • GCP Project • GCP Project
  • 24. configurations { invoker } dependencies { implementation "...:functions-framework-api:$ver" invoker "...:java-function-invoker:$ver" } tasks.register("runFunction", JavaExec) { main = '...' classpath(configurations.invoker) inputs.files(..., ...) args( '--target', ...Property('runFunction.target') ?: '', '--port', ...Property('runFunction.port') ?: ... ) doFirst { args('--classpath', ...) } } Gradle — Cloud Function • functions-framework-api • java-function-invoker Gradle Task $ gradle runFunction Java Invoker
  • 25. class Handler: HttpFunction { @Throws(IOException::class) override fun service(req: HttpRequest, res: HttpResponse) { } } Handler — • Class • HttpFunction ( functions-framework-api) • service() • req res
  • 26. class Handler: HttpFunction { @Throws(IOException::class) override fun service(req: HttpRequest, res: HttpResponse) { val param = request.getFirstQueryParameter("amount") .orElse("") val amount = param.toIntOrNull() ?: 10 } } Query — • HttpRequest Query •
  • 27. class Handler: HttpFunction { @Throws(IOException::class) override fun service(req: HttpRequest, res: HttpResponse) { val param = request.getFirstQueryParameter("amount") .orElse("") val amount = param.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) } } / — • Service • JSON
  • 28. class Handler: HttpFunction { @Throws(IOException::class) override fun service(req: HttpRequest, res: HttpResponse) { val param = request.getFirstQueryParameter("amount") .orElse("") val amount = param.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) with(res) { setStatusCode(HttpURLConnection.HTTP_OK) setContentType("application/json") writer.write(jsonString) } } } Response — • HTTP Status Code • Content-Type • JSON
  • 29. $ ./gradlew runFunction -PrunFunction.target=CLASS -PrunFunction.port=PORT — • Gradle Task • Run Configuration
  • 30. $ gcloud functions deploy PUBLIC_PATH --region REGION --runtime java11 --trigger-http --memory 256MB --entry-point ENTRY_POINT_CLASS --allow-unauthenticated — • gcloud
  • 31. Azure Functions — • IntelliJ IDEA + Plugins • JDK 8 • Azure CLI • Azure Functions Core Tools Repository: https://github.com/shengyou/microsoft-azure-functions-kotlin
  • 32. $ brew update $ brew install azure-cli $ az login $ az account -a SUBSCRIPTION_ID $ brew tap azure/functions $ brew installazure-function-core-tools@3 — • Azure CLI • Azure • Azure Functions Core Tools • Azure Toolkit for IntelliJ
  • 33. 1. Azure Functions 2. Gradle 3. JDK 8 —
  • 34. 1. Azure Functions 2. Gradle 3. JDK 8 Kotlin — ① ② ③ ④
  • 36. class Handler { @FunctionName("...") fun run( @HttpTrigger( name = "...", route = "...", methods = [HttpMethod.GET], authLevel = AuthorizationLevel.ANONYMOUS ) request: HttpRequestMessage<Optional<String?>>, context: ExecutionContext ): HttpResponseMessage { // ... } } Handler — • Class Method • Annotation • route methods • request context
  • 37. class Handler { @FunctionName("...") fun run(/* . . . */): HttpResponseMessage { val query = request.queryParameters["amount"] val amount = query?.toIntOrNull() ?: 10 } } Query — • request Query •
  • 38. class Handler { @FunctionName("...") fun run(/* . . . */): HttpResponseMessage { val query = request.queryParameters["amount"] val amount = query?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) } } / — • Service • JSON
  • 39. class Handler { @FunctionName("...") fun run(/* . . . */): HttpResponseMessage { val query = request.queryParameters["amount"] val amount = query?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) return request.createResponseBuilder(HttpStatus.OK) .header("Content-Type", "application/json") .body(jsonString) .build() } } Response — • HTTP Status Code • Content-Type • JSON
  • 41. azurefunctions { subscription = '...' resourceGroup = '...' appName = '...' pricingTier = 'Consumption' region = '...' runtime { os = 'linux' } authentication { type = 'azure_cli' } } — • Azure Gradle • Gradle Task
  • 42. AWS Lambda — • IntelliJ IDEA + Plugin • JDK 11 • Docker • AWS CLI • AWS SAM CLI Repository: https://github.com/shengyou/amazon-lambda-kotlin
  • 43. $ brew update $ brew install awscli $ aws configure $ aws sts get-caller-identity $ brew tap aws/tap $ brew install aws-sam-cli — • AWS CLI • AWS • Account ID • IAM (User & Role) • AWS SAM CLI • AWS Toolkit
  • 44. 1. Kotlin 2. Gradle 3. JDK 11 — 1. AWS
  • 45. plugins { id 'java' id 'com.github.johnrengelman.shadow' version '6.1.0' } dependencies { implementation "...:aws-lambda-java-core:1.2.1" implementation "...:aws-lambda-java-events:3.1.0" runtimeOnly "...:aws-lambda-java-log4j2:1.2.0" } Gradle — AWS Lambda • aws-lambda-java-core • aws-lambda-java-events • aws-lambda-java-log4j2 Gradle Plugin • java • shadow
  • 46. class Handler : RequestHandler < APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent > { @Throws(IOException::class) override fun handleRequest( request: APIGatewayProxyRequestEvent, context: Context ): APIGatewayProxyResponseEvent { // ... } } Handler — • Class Method • RequestHandler ( aws- lambda-java-core) • Handler Method • reqest context
  • 47. class Handler : RequestHandler <...> { @Throws(IOException::class) override fun method(/* ... */): ...ResponseEvent { val param = request.queryStringParameters["amount"] val amount = param?.toIntOrNull() ?: 10 } } Query — • request Query •
  • 48. class Handler : RequestHandler <...> { @Throws(IOException::class) override fun method(/* ... */): ...ResponseEvent { val param = request.queryStringParameters["amount"] val amount = param?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) } } / — • Service • JSON
  • 49. class Handler : RequestHandler <...> { @Throws(IOException::class) override fun method(/* ... */): ...ResponseEvent { val param = request.queryStringParameters["amount"] val amount = param?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val jsonString = Json.encodeToString( mapOf("data" to contacts) ) return APIGatewayProxyResponseEvent() .withStatusCode(HttpURLConnection.HTTP_OK) .withHeaders( mapOf("Content-Type" to "application/json") ) .withBody(jsonString) } } Response — • HTTP Status Code • Content-Type • JSON
  • 50. $ aws lambda create-function --function-name NAME --zip-file fileb://build/libs/SHADOWJAR.jar --handler CLASS::METHOD --runtime java11 --timeout 15 --memory-size 128 --role ROLE — • aws • AWS Console
  • 52. JDK 11 8 11 IntelliJ Plugin ✗ ✓ ✓ Gradle ✓ ✓ Framework ✓ ✓ ✓ + —
  • 54. Kotless — https://site.kotless.io/ • Serverless Framework • Kotless DSL • Gradle Plugin • Developed by Vladislav Tankov from JetBrains • Open Source (Apache 2.0)
  • 55. — Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
  • 56. 1. Kotlin 2. Gradle Kotlin ❤ 3. JDK 11 —
  • 57. plugins { kotlin("jvm") version "1.3.72" apply true kotlin("plugin.serialization") version "1.3.72" id("io.kotless") version "0.1.6" apply true } dependencies { implementation("io.kotless", "kotless-lang", "0.1.6") } Gradle — Gradle Plugins • Kotlin 1.3.72 • Serialization 1.3.72 • Kotless 0.1.6 • Kotless
  • 58. @Get("/") fun handler(): HttpResponse { val dom = """ // ... """.trimIndent() return html(dom) } Function — • Function • Annotation Route • HttpResponse
  • 59. @Get("/...") fun handler(): HttpResponse { val param = KotlessContext.HTTP.request.params?.get("amount") val amount = param?.toIntOrNull() ?: 10 } Query — • KotlessContext Query •
  • 60. @Get("/...") fun handler(): HttpResponse { val param = KotlessContext.HTTP.request.params?.get("amount") val amount = param?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val json = Json(JsonConfiguration.Stable) val jsonString = json.stringify( Contact.serializer(), contacts ) } / — • Service • JSON
  • 61. @Get("/...") fun handler(): HttpResponse { val param = KotlessContext.HTTP.request.params?.get("amount") val amount = param?.toIntOrNull() ?: 10 val contacts = ContactService().generate(amount) val json = Json(JsonConfiguration.Stable) val jsonString = json.stringify( Contact.serializer(), contacts ) return json(jsonString) } Response — • JSON
  • 63. kotless { config { bucket = "..." terraform { profile = "..." region = "..." } } } — • AWS CLI Credentials • S3 Bucket • AWS Gradle • Gradle Task
  • 65. Kotless — Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
  • 66. 1. Ktor (1.3.2) 2. Gradle Kotlin ❤ 3. JDK 11 4. Server Features • Routing • ContentNegotiation • Jackson Ktor —
  • 67. plugins { id("io.kotless") version "0.1.6" apply true } dependencies { // ... implementation("io.ktor:ktor-server-netty:$ktor_version") // ... implementation("io.kotless", "ktor-lang", “0.1.6") // ... } Gradle — Gradle Plugins • Kotless 0.1.6 • Netty • Kotless for Ktor
  • 68. class Server : Kotless() { override fun prepare(app: Application) { app.install(ContentNegotiation) { jackson { enable(SerializationFeature.INDENT_OUTPUT) } } app.routing { // ... } } } Kotless App — Kotless App • Kotless • prepare() • Ktor app
  • 69. // Application.kt @Suppress("unused") @kotlin.jvm.JvmOverloads fun Application.module(testing: Boolean = false) { // ... } // resources/application.conf ktor { deployment { port = 8080 port = ${?PORT} } application { modules = [ io.kraftsman.Server.prepare ] } } — • Application.kt •
  • 70. Roadmap — Image source: Serverless Development With Kotlin and Kotless by Vlaadislav Tankov
  • 71. % & % Repository: https://github.com/shengyou/jetbrains-kotless-framework Repository: https://github.com/shengyou/jetbrains-ktor-with-kotless
  • 72. — • Serverless • Kotlin Serverless • Kotless Framework • Kotless
  • 73. Serverless — • IBM Bluemix • Cloudflare Workers • Alibaba Cloud • Huawei Cloud • …
  • 74. Serverless — • Fat Jar • Container • Kotlin/JS
  • 75. Serverless — • Spring Cloud Function • Micronaut • Osiris • Nimbus • …
  • 76. — • Mobile Backend (API …) • Webhook ( API …) • ( …)
  • 77. — • • • • Image source: The Definition of Framework by Francesco Strazzullo