A presentation at Droidcon Berlin 2018 in in Berlin, Germany by Annyce Davis
@BRWNGRLDEV
@BRWNGRLDEV 2013-2014
@BRWNGRLDEV U.S.A
@BRWNGRLDEV 891 TIMES
GETTING A GRIP ON GRAPHQL @BRWNGRLDEV
@BRWNGRLDEV AGENDA
@BRWNGRLDEV Basics AGENDA
@BRWNGRLDEV Basics Server AGENDA
@BRWNGRLDEV Basics Server Client AGENDA
BASICS @BRWNGRLDEV
@BRWNGRLDEV GraphQL is… A QUERY LANGUAGE FOR YOUR API
@BRWNGRLDEV SELECT name FROM users
@BRWNGRLDEV SELECT name FROM users
@BRWNGRLDEV SELECT name FROM users
@BRWNGRLDEV Karen Aisha James SELECT name FROM users
@BRWNGRLDEV data class UFOSighting( var id: Int , var date: LocalDate , var city: String? , var state: String? , var country: String? , var shape: String? , var duration: Double , var comments: String? , var latitude: Double , var longitude: Double
)
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} }
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} }
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} }
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} }
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} }
@BRWNGRLDEV query AllSightings { sightings
{ id shape
} } API
@BRWNGRLDEV query AllSightings {
sightings { id shape
} } { 8
“data” : { “sightings” : [ { 8
“id” : 1,
“shape” : “circle”
}
8
]
8
} 8
} 8 API
@BRWNGRLDEV { 8
“ data ” : { “sightings” : [ { 8
“id” : 1,
“shape” : “circle”
}
8
]
8
} 8
} 8
@BRWNGRLDEV { “data” : { “sightings” : [ { “id” : 1, “shape” : “circle” } ] } }
@BRWNGRLDEV query
@BRWNGRLDEV GET query
@BRWNGRLDEV GET query mutation POST PUT PATCH DELETE
@BRWNGRLDEV BLOG
@BRWNGRLDEV User BLOG
@BRWNGRLDEV User Post BLOG
@BRWNGRLDEV User Post Comment BLOG
@BRWNGRLDEV BLOG User Post Comment
@BRWNGRLDEV GraphQL is… A SPECIFICATION
@BRWNGRLDEV
@BRWNGRLDEV Give me some data!
@BRWNGRLDEV You didn’t say please!
@BRWNGRLDEV C# / .NET Elixir Kotlin Java JavaScript Ruby … Server
@BRWNGRLDEV C# / .NET Go Java / Android JavaScript Python Swift … Client
@BRWNGRLDEV GraphQL is… INTROSPECTIVE
@BRWNGRLDEV query { __type(name: "UFOSighting") { fields { name } } }
@BRWNGRLDEV query {
__type (name: "UFOSighting") { fields { name } } }
@BRWNGRLDEV query { __type(name: "UFOSighting") { fields { name } } }
@BRWNGRLDEV
@BRWNGRLDEV GraphQL is… a query language a specification introspective
@BRWNGRLDEV SO WHAT?!
@BRWNGRLDEV R E S T
@BRWNGRLDEV R E S T /UFO-SIGHTINGS [ { "ID": 9298, "LONGITUDE": 145.722595, "LATITUDE": -38.626591, "STATE": "", "COUNTRY": "AU", "SHAPE": "LIGHT", "COMMENTS": "BRIGHT ORANGE LIGHT” }, { "ID": 9297, "LONGITUDE": -90.0488889, "LATITUDE": 35.1494444, "STATE": "TN", "COUNTRY": "US", "SHAPE": "RECTANGLE", "COMMENTS": "STANDING AT MY WINDOW” }, { "ID": 9287, "LONGITUDE": -3.1, "LATITUDE": 53.316667, "STATE": "YT", "COUNTRY": "GB", "SHAPE": "TRIANGLE", "COMMENTS": "((HOAX??)) LONG TRIANGLE OBJECT” }, …
@BRWNGRLDEV R E S T G R A P H Q L
@BRWNGRLDEV
@BRWNGRLDEV
@BRWNGRLDEV
SERVER @BRWNGRLDEV
@BRWNGRLDEV Single Endpoint /graphql
@BRWNGRLDEV HTTP GET
/GRAPHQL?QUERY= <QUERY>
@BRWNGRLDEV
HTTP GET
/GRAPHQL?QUERY= <QUERY> “{
sightings { id shape
} }”
@BRWNGRLDEV HTTP POST
/GRAPHQL
@BRWNGRLDEV {
“query” : “{ sightings
{ id shape
} }” } HTTP POST
/GRAPHQL
@BRWNGRLDEV Postman
@BRWNGRLDEV Postman
@BRWNGRLDEV BUILDING OUR SERVER
@BRWNGRLDEV Ktor – Server Framework
@BRWNGRLDEV Ktor – Server Framework Koin – Dependency Injection
@BRWNGRLDEV Ktor – Server Framework Koin – Dependency Injection Squash – Database Access
@BRWNGRLDEV Ktor – Server Framework Koin – Dependency Injection Squash – Database Access KGraphQL – GraphQL Support
@BRWNGRLDEV GraphQL Server… Types Schema Resolvers
@BRWNGRLDEV
C S S H N A S V Z U Y C J H M
N I W P X O D C B Q Q G L F T
C P B U H Z I B A U M A Q S V
Q O W G Y F M T E L M A H F H
R E V L O S E R A E A T P I R
K F S R R S Y N H T P R A E J
O B J E C T S C U L U D R L P
E P Y T L O S X L U B M G D X
@BRWNGRLDEV
C S S H N A S V Z U Y C J H M
N I W P X O D C B Q Q G L F T
C P B U H Z I B A U M A Q S V
Q O W G Y F M T E L M A H F H
R E V L O S E R A E A T P I R
K F S R R S Y N H T P R A E J
O B J E C T S C U L U D R L P
E P Y T L O S X L U B M G D X
@BRWNGRLDEV type UFOSighting {
id: Int! city: String
}
@BRWNGRLDEV type UFOSighting {
id: Int! city: String
}
@BRWNGRLDEV type UFOSighting {
id: Int! city: String
} { sightings
{
id {
???
}
city
}
}
@BRWNGRLDEV type UFOSighting {
id: Int! city: String
} { sightings
{
id {
???
}
city
}
}
WRONG!
@BRWNGRLDEV type <UFOSighting>
@BRWNGRLDEV type<UFOSighting> data class UFOSighting( var id: Int = -1, var city: String? = "", )
@BRWNGRLDEV type<UFOSighting> data class UFOSighting( var id: Int = -1, var city: String? = "", )
@BRWNGRLDEV type <UFOSighting> data class UFOSighting( var id: Int = -1, var city: String? = "", ) type UFOSighting {
id: Int! city: String
}
@BRWNGRLDEV
C S S H N A S V Z U Y C J H M
N I W P X O D C B Q Q G L F T
C P B U H Z I B A U M A Q S V
Q O W G Y F M T E L M A H F H
R E V L O S E R A E A T P I R
K F S R R S Y N H T P R A E J
O B J E C T S C U L U D R L P
E P Y T L O S X L U B M G D X
@BRWNGRLDEV schema {
query: Query
}
@BRWNGRLDEV type Query {
sighting (id: Int) :
UFOSighting
} schema { query: Query }
@BRWNGRLDEV type UFOSighting {
id: Int! city: String
} type Query {
sighting(id: Int): UFOSighting
} schema { query: Query }
@BRWNGRLDEV Data, please! Why, yes!
@BRWNGRLDEV KGraphQL. schema {
}
@BRWNGRLDEV KGraphQL.schema {
type <UFOSighting> }
@BRWNGRLDEV KGraphQL.schema {
type <UFOSighting>
query ( "sighting" ) { resolver { id: Int -> …} } }
@BRWNGRLDEV
C S S H N A S V Z U Y C J H M
N I W P X O D C B Q Q G L F T
C P B U H Z I B A U M A Q S V
Q O W G Y F M T E L M A H F H
R E V L O S E R A E A T P I R
K F S R R S Y N H T P R A E J
O B J E C T S C U L U D R L P
E P Y T L O S X L U B M G D X
@BRWNGRLDEV Resolver query ("sighting") { 3
resolver { 3 id: Int ->
storage .getSighting(id) } 3
} 3
@BRWNGRLDEV Resolver query ("sighting") { 3 resolver { 3 id: Int ->
“http://sightings/ $id " .httpGet()
} 3
} 3
@BRWNGRLDEV { sighting(id: 45) { id shape user { id name } } }
@BRWNGRLDEV { sighting(id: 45) {
id shape user { id name } } } Root Query sighting
@BRWNGRLDEV { sighting(id: 45) { id shape user { id name } } } Root Query sighting 345 circle
@BRWNGRLDEV { sighting(id: 45) { id shape user { id name } } } Root Query sighting 345 circle user 24 Shuri
@BRWNGRLDEV mutation ( "createUFOSighting" ) { description = "Adds a new UFO Sighting”
} 3 Resolver - Mutation
@BRWNGRLDEV Resolver - Mutation mutation("createUFOSighting") { description = "Adds a new UFO Sighting” resolver { input: CreateUFOSightingInput ->
storage .createSighting(input…) } } 3
@BRWNGRLDEV Resolver - schema.json
@BRWNGRLDEV /graphql Endpoint fun Route .graphql(…) {
post <GraphQLRequest> { val request = call.receive<GraphQLRequest>() val query = request.query val variables = gson.toJson(request.variables) val result = schema. execute (query, variables) call.respondText(result) } }
@BRWNGRLDEV /graphql Endpoint fun Route.graphql(…) { post<GraphQLRequest> { val request = call.receive<GraphQLRequest>() val query = request.query val variables = gson.toJson(request.variables) val result = schema.execute(query, variables) call.respondText(result) } }
@BRWNGRLDEV schema resolvers /graphql
CLIENT @BRWNGRLDEV
@BRWNGRLDEV Sample Application
@BRWNGRLDEV Sample Application KOTLIN
@BRWNGRLDEV Sample Application KOTLIN ARCHITECTURE COMPONENTS
@BRWNGRLDEV Sample Application KOTLIN ARCHITECTURE COMPONENTS APOLLO ANDROID
@BRWNGRLDEV GraphQL Client… Apollo Client Schema .graphql Files
@BRWNGRLDEV Apollo Client ApolloClient.builder() . serverUrl ( BASE_URL ) . okHttpClient ( okHttpClient ) .build()
@BRWNGRLDEV Apollo Client ApolloClient.builder() .serverUrl(BASE_URL) .okHttpClient(okHttpClient)
.build()
@BRWNGRLDEV apollo-codegen download-schema
@BRWNGRLDEV Schema
@BRWNGRLDEV .graphql File
@BRWNGRLDEV .graphql File
@BRWNGRLDEV .graphql File Plugin
@BRWNGRLDEV .graphql File Plugin
@BRWNGRLDEV
@BRWNGRLDEV Generated Code…
@BRWNGRLDEV Apollo Client Schema .graphql Files
@BRWNGRLDEV 1. Build our query 2. Enqueue the request 3. Handle the response
@BRWNGRLDEV SightingsQuery.builder() .size( 30 ) .build() Build our query
@BRWNGRLDEV apolloClient .query( query ) Enqueue the request
@BRWNGRLDEV apolloClient .query(query) .enqueue(object : Callback<T>() { }) Enqueue the request
@BRWNGRLDEV apolloClient .query(query) .enqueue(object : Callback<T>() { fun onResponse (response: Response<T>) fun onFailure (e: ApolloException) }) Enqueue the request
@BRWNGRLDEV Handle the response {
"data" : {
"sightings" : [ { "__typename" : "UFOSighting", "id" : 9297, "date" : "2014-05-08", "shape" : "rectangle", "comments" : "Standing at my window one by one." } ] } }
@BRWNGRLDEV Handle the response fun onResponse (response: Response<T>) { response. data ()?. sightings ()
// notify your UI
}
@BRWNGRLDEV
TIPS & TRICKS @BRWNGRLDEV
@BRWNGRLDEV IntelliJ GraphQL Plugin…
@BRWNGRLDEV A CLIENT IS OPTIONAL
@BRWNGRLDEV HTTPS://GITHUB.COM/APIS-GURU/GRAPHQL-APIS
@BRWNGRLDEV HTTPS://GITHUB.COM/SOGKO/GRAPHQL-SCHEMA-LANGUAGE-CHEAT-SHEET
@BRWNGRLDEV TRUE / FALSE RAPID
FIRE @BRWNGRLDEV
@BRWNGRLDEV GRAPHQL WAS DESIGNED FOR GRAPH DATABASES. @BRWNGRLDEV
@BRWNGRLDEV GRAPHQL WAS DESIGNED FOR GRAPH DATABASES. FALSE @BRWNGRLDEV
@BRWNGRLDEV GRAPHQL IS LANGUAGE AGNOSTIC. @BRWNGRLDEV
@BRWNGRLDEV GRAPHQL IS LANGUAGE AGNOSTIC. TRUE @BRWNGRLDEV
@BRWNGRLDEV APOLLO ANDROID IS THE ONLY GRAPHQL CLIENT. @BRWNGRLDEV
@BRWNGRLDEV APOLLO ANDROID IS THE ONLY GRAPHQL CLIENT. FALSE @BRWNGRLDEV
@BRWNGRLDEV REST IS DEAD. @BRWNGRLDEV
@BRWNGRLDEV YOU DECIDE @BRWNGRLDEV
GETTING A GRIP ON GRAPHQL @BRWNGRLDEV
ADAVIS.INFO
GraphQL is a query language for your API. This allows you to interact with your existing web services and databases in a new way. Instead of relying on a predetermined output structure from your API, you can “query” it and choose only the fields that you’re interested in.
In this talk, learn what GraphQL is all about and how you can take advantage of it in your applications.
A few key GraphQL terms we'll cover are:
Then we'll take a look at how you can integrate the Apollo Client library inside of an Android application. GraphQL isn't going away, so here's your chance to get a grip on this exciting technology!
The following resources were mentioned during the presentation or are useful additional information.