Building APIs in Java is not exciting. That changes if you throw GraphQL and Kotlin into the mix. The great library (thanks Andy) and powerful, concise language make it easy to build a GraphQL server in a few lines of code. With co-routines and lambdas as a glue, you get a neat, scalable backend.
https://www.youtube.com/watch?v=3-yyEaQfm9c
17. class GraphQLHandler(private val schema:GraphQLSchema) {
suspend fun execute(query: String, params: Map<String, Any>, op:String?, ctx : Any?): ExecutionResult {
val graphql = GraphQL.newGraphQL(schema).build()
val executionResult = graphql.executeAsync{
builder -> builder.query(query).variables(params).operationName(op).context(ctx) }
return executionResult.await()
}
}
GraphQL-Kotlin - Execute
async via co-routines
18. fun main(args: Array<String>) {
runBlocking {
val schema = """type Query {
answer: Int
hello(what:String="World"): String
}"""
val resolvers = mapOf("Query" to
listOf("hello" to DataFetcher { env -> "Hello"+env.getArgument("what") },
"answer" to StaticDataFetcher(42)))
with(GraphQLHandler(schema, resolvers)) {
val result = execute(args.first(), args.drop(1).zipWithNext().toMap())
println(result.getData() as Any)
}
}
}
GraphQL-Kotlin - Run
Run main: "query($p:String) { hello(what:$p) }" p GraphQL
Output: {hello=Hello GraphQL}
21. Kotlin Web Server
val server = embeddedServer(Netty, port = 8080) {
install(ContentNegotiation) { jackson { } }
routing {
get("/") {
call.respondText("Hello World!n", ContentType.Text.Plain)
}
get("/json") {
call.respond(mapOf("OK" to true))
}
post("/post/{name}") {
val body = call.receive<Text>()
call.respond(Text(body.text+" from "+call.parameters["name"]))
}
get("/html") {
call.respondHtml {
head { title { +"Title"} }
body { p { +"Body" }}
}
}
}
}
server.start(wait = true)
localhost:8080/
Hello World!
localhost:8080/json
{"OK":true}
localhost:8080/post/Joe -d'{"text":"Hi"}'
-H content-type:application/json
{"text":"Hi from Joe"}
localhost:8080/html
<html>
<head>
<title>Title</title>
</head>
<body>
<p>Body</p>
</body>
</html>
22. GraphQL Http Server
fun main(args: Array<String>) {
val schema = """type Query {
answer: Int
hello(what:String="World"): String
}"""
val fetchers = mapOf("Query" to
listOf("hello" to DataFetcher { env -> "Hello "+env.getArgument("what") },
"answer" to StaticDataFetcher(42)))
val handler = GraphQLHandler(schema, fetchers)
data class Request(val query:String, val params:Map<String,Any>, val operationName : String?)
val server = embeddedServer(Netty, port = 8080) {
install(ContentNegotiation) { jackson { } }
routing {
post("/graphql") {
val request = call.receive<Request>()
val result = handler.execute(request.query, request.params)
call.respond(mapOf("data" to result.getData<Any>()))
}
}
}
server.start(wait = true)
}
23. GraphQL Server
data class Request(val query:String, val variables:Any?, val operationName : String?) {
// for GraphiQL
val params get() =
when (variables) {
is String -> MAPPER.readValue(variables, Map::class.java)
is Map<*, *> -> variables
else -> emptyMap<String, Any>()
} as Map<String, Any>
}
24. GraphQL Server (Response)
curl localhost:8080/graphql
-H content-type:application/json
-d'{"query":"{answer}"}'
{"data":{"answer":42}}
28. Kotlin JavaScript
● Cross compile to JavaScript
● Include kotlin.js std library (npm install kotlin)
● Use existing JS libraries with TypeScript headers (ts2kt) or
● turn them into dynamic objects with asDynamic()
● Reuse common (business) code in multi-platform projects
● Node and Web support, incl. DOM
29. JavaScript
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = { hello: () => { return 'Hello world!'; },};
var app = express();
app.use('/graphql', graphqlHTTP({schema: schema, rootValue: root, graphiql: true}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
graphql.org/graphql-js/running-an-express-graphql-server/
30. Kotlin JavaScript
external fun require(module:String):dynamic
val express = require("express")
val graphqlHTTP = require("express-graphql");
val buildSchema = require("graphql").buildSchema;
val schema = buildSchema("""
type Query {
hello(what:String="World"): String
}
""")
fun main(args: Array<String>) {
val root = asObject("hello" to {ctx:dynamic -> "Hello ${ctx["what"]}"})
val options = asObject("schema" to schema, "rootValue" to root, "graphiql" to true)
val app = express()
app.use("/graphql-js", graphqlHTTP(options))
app.listen(3000, {
println("Server started")
})
}
kotlinlang.org/docs/tutorials/javascript/
33. Kotlin Native
● using LLVM, cross-compile to LLVM-IR
● iOS, Android, Windows, OSX, Unix, WebAssembly
● Use native libs
● Interop with Swift, C / C++, ...
● generate native libs and executables
● use typesafe, clean Kotlin code
34. Kotlin Native
● use microHttpd (MHD) as webserver
● use github.com/graphql/libgraphqlparser
for schema & query parsing
● resolvers as callback functions
● use any db connection or libcurl for API calls for
resolvers
35. ● KGraphQL - Pure Kotlin GraphQL implementation
● kraph: GraphQL request string builder in Kotlin
● Ktor + Koin + KGraphQL + Squash
● Android/Apollo + GraphKool + GraphQL Java Server
● Writing a GraphQL Server in Kotlin
Other Notables
36. ● Micronaut.io Framework (Java, Groovy, Kotlin)
○ GraphQL Demo
● GraphQL Server via GORM
● GraphQL with Kotlin + Spring Boot
Other Notables