Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQL In Real Life

GraphQL In Real Life

Roberto Orgiu

April 05, 2019
Tweet

More Decks by Roberto Orgiu

Other Decks in Programming

Transcript

  1. film
    character
    species
    homeworld
    episode

    View Slide

  2. film
    character
    species
    homeworld
    episode
    GR APHQL
    IN REAL L IFE
    ROBERTO ORGIU - @_TIWIZ

    View Slide

  3. the
    problem

    View Slide

  4. the
    portrait
    version
    I N T R O D U C I N G

    View Slide

  5. the
    landscape
    version
    W H I C H B E C O M E S

    View Slide

  6. Fun fact
    GraphQL.replace(REST)
    usually returns false

    View Slide

  7. Architectural
    Pattern
    Query
    Language

    View Slide

  8. Leverage
    Protocol
    Use own
    Conventions

    View Slide

  9. Versioning
    Evolution

    View Slide

  10. Full request
    Client
    Performances

    View Slide

  11. Ease of
    Caching
    DIY Cache

    View Slide

  12. Query
    Strings
    Query
    Language

    View Slide

  13. Multiple
    Endpoints
    Single
    Endpoint

    View Slide

  14. Unified
    Precise

    View Slide

  15. What is GraphQ
    What is GraphQL?
    D E E P D I V E I N T O

    View Slide

  16. graphqlbin.com
    GraphQLBin
    insomnia.rest/graphql
    Insomnia
    altair.sirmuel.design
    Altair
    swapi.graph.cool
    GraphCool
    graphql.org/swapi-graphql
    GraphiQL

    View Slide

  17. View Slide

  18. WHY APOLLO?
    Compile time safety
    Caching
    Community
    Code generation

    View Slide

  19. buildscriptT{
    repositoriesT{
    google()T
    }A
    dependenciesT{
    classpathA"com.android.tools.build:gradle:$tools_version"
    classpathB"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }B
    }C
    allprojectsT{
    repositoriesB{
    google()B
    }D
    }E

    View Slide

  20. buildscriptT{
    repositoriesT{
    google()T
    jcenter()
    }A
    dependenciesT{
    classpathA"com.android.tools.build:gradle:$tools_version"
    classpathB"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath "com.apollographql.apollo:gradle-plugin:$apollo_version"
    }B
    }C
    allprojectsT{
    repositoriesB{
    google()B
    jcenter()
    }D
    }E

    View Slide

  21. buildscriptT{
    repositoriesT{
    google()T
    jcenter()
    }A
    dependenciesT{
    classpathA"com.android.tools.build:gradle:$tools_version"
    classpathB"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath "com.apollographql.apollo:gradle-plugin:$apollo_version"
    }B
    }C
    allprojectsT{
    repositoriesB{
    google()B
    jcenter()
    }D
    }E

    View Slide

  22. apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    android {
    ...
    }

    View Slide

  23. apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'com.apollographql.android'
    android {
    ...
    }

    View Slide

  24. dependencies {
    ...
    implementation "com.apollographql.apollo:apollo-runtime:$apollo_version"
    implementation "com.apollographql.apollo:apollo-rx2-support:$apollo_version"
    ...
    }

    View Slide

  25. DOWNSIDES
    Apollo-plugin
    schema.json
    *.graphql
    X X

    View Slide

  26. testing

    View Slide

  27. testing
    Compile time safety
    MockWebServer

    View Slide

  28. > Task :apollo:generateDebugApolloIR FAILED
    .../android/apollo/Query.graphql: Cannot query field "nam" on
    type "YourType". Did you mean "name"?
    error: Validation of GraphQL query document failed
    FAILURE: Build failed with an exception.

    View Slide

  29. @get:Rule
    val mockWebServer = MockWebServerRule()
    mockWebServer.enqueueResponse("/response.json")
    val testApolloClient =
    ApolloClient.builder()
    .serverUrl(mockWebServer.url)
    .okHttpClient(client)
    .build()

    View Slide

  30. WHY?

    View Slide

  31. CDN
    Android Back end
    Cache
    8 KB limit

    View Slide

  32. Solutions
    2 solutions
    O k H t t p
    I n t e r c e p t o r
    A u t o m a t i c
    P e r s i s t e d Q u e r i e s
    W e f o u n d

    View Slide

  33. query filmById($filmId: ID){
    film(filmID :$filmId){
    title
    episodeID
    characterConnectionT{
    charactersT{
    name
    homeworldT{
    name
    }A
    speciesT{
    name
    classification
    }B
    filmConnectionT{
    filmsT{
    title
    episodeID
    }C
    }D
    }E
    }F
    }G
    }H
    A u t o m a t i c
    P e r s i s t e d Q u e r i e s

    View Slide

  34. query filmById($filmId: ID){
    film(filmID :$filmId){
    title
    episodeID
    characterConnectionT{
    charactersT{
    name
    homeworldT{
    name
    }A
    speciesT{
    name
    classification
    }B
    filmConnectionT{
    filmsT{
    title
    episodeID
    }C
    }D
    }E
    }F
    }G
    }H
    A u t o m a t i c
    P e r s i s t e d Q u e r i e s
    variables {
    "filmId" : 1
    }A
    query: query filmById($filmId: ID) {
    film(filmId :$filmId) {
    title
    episodeID
    characterConnection {
    name
    homeworld{
    name
    }B
    species {
    name
    classification
    }C
    filmConnection {
    films {
    title
    episodeID
    }D
    }E
    }F
    }G
    }H
    operationName: filmById

    View Slide

  35. query filmById($filmId: ID){
    film(filmID :$filmId){
    title
    episodeID
    characterConnectionT{
    charactersT{
    name
    homeworldT{
    name
    }A
    speciesT{
    name
    classification
    }B
    filmConnectionT{
    filmsT{
    title
    episodeID
    }C
    }D
    }E
    }F
    }G
    }H
    A u t o m a t i c
    P e r s i s t e d Q u e r i e s
    variables {
    "filmId" : 1
    }A
    query: query filmById($filmId: ID) {
    film(filmId :$filmId) {
    title
    episodeID
    characterConnection {
    name
    homeworld{
    name
    }B
    species {
    name
    classification
    }C
    filmConnection {
    films {
    title
    episodeID
    }D
    }E
    }F
    }G
    }H
    operationName: filmById
    operationName: filmById
    variables {
    "filmId" : 1
    }T

    View Slide

  36. query filmById($filmId: ID){
    film(filmID :$filmId){
    title
    episodeID
    characterConnectionT{
    charactersT{
    name
    homeworldT{
    name
    }A
    speciesT{
    name
    classification
    }B
    filmConnectionT{
    filmsT{
    title
    episodeID
    }C
    }D
    }E
    }F
    }G
    }H
    A u t o m a t i c
    P e r s i s t e d Q u e r i e s
    variables {
    "filmId" : 1
    }A
    query: query filmById($filmId: ID) {
    film(filmId :$filmId) {
    title
    episodeID
    characterConnection {
    name
    homeworld{
    name
    }B
    species {
    name
    classification
    }C
    filmConnection {
    films {
    title
    episodeID
    }D
    }E
    }F
    }G
    }H
    operationName: filmById
    operationName: filmById
    variables {
    "filmId" : 1
    }T

    View Slide

  37. A u t o m a t i c
    P e r s i s t e d Q u e r i e s
    operationName: filmById
    variables {
    "filmId" : 1
    }T
    extensions: {
    persistedQuery: {
    "version": 1,
    "sha256Hash": "queryHash"
    }
    }

    View Slide

  38. Android Back end
    Query Hash
    Query Hash Not Found
    Whole Query + Query Hash
    Response

    View Slide

  39. @get:Rule
    valTmockWebServerT=TMockWebServerRule()
    mockWebServer.enqueueResponse(“/response.json")
    valTurlT=TmockWebServer.url
    valßapolloClientT=
    ApolloClient.builder()
    .serverUrl(url)
    .okHttpClient(client)
    .build()

    View Slide

  40. valßapolloClientT=
    ApolloClient.builder()
    .serverUrl(url)
    .okHttpClient(client)
    .build()

    View Slide

  41. valßapolloClientT=
    ApolloClient.builder()
    .serverUrl(url)
    .okHttpClient(client)
    .enableAutoPersistedQueries(true)
    .build()

    View Slide

  42. Tricks
    Tricks
    J U S T S O M E
    query SampleQuery {
    assetID: sourceId
    fingerprint: modified
    headlineInfo: headline {
    __typename
    headline: default
    }A
    lastUpdated: lastModification
    }B

    View Slide

  43. Tricks
    Tricks
    L A B E L F I E L D S C A N G O
    A L O N G D I S T A N C E
    J U S T S O M E
    query SampleQuery {
    assetID: sourceId
    fingerprint: modified
    headlineInfo: headline {
    __typename
    headline: default
    }A
    lastUpdated: lastModification
    }B

    View Slide

  44. Tricks
    Tricks
    A P O L L O A D D S
    T Y P E N A M E E V E R Y W H E R E
    J U S T S O M E
    query SampleQuery {
    assetID: sourceId
    fingerprint: modified
    headlineInfo: headline {
    __typename
    headline: default
    }A
    lastUpdated: lastModification
    }B

    View Slide

  45. Tricks
    Tricks
    S C H E M A A N D Q U E R I E S
    C A N B E M O V E D
    J U S T S O M E
    apollo {
    schemaFilePath = "/path/my-schema.json"
    outputPackageName = "pkg.graphql.api"
    }

    View Slide

  46. Tricks
    Tricks
    S U P P O R T S F O R J A V A
    B E A N S E M A N T I C S
    J U S T S O M E
    class Type {
    public Another getAnother() { ... }
    }
    //build.gradle
    apollo {
    useJavaBeansSemanticNaming = true
    }

    View Slide

  47. Tricks
    Tricks
    R E M E M B E R T O
    B E O N L I N E ¯ \ _ ( ツ ) _ / ¯
    J U S T S O M E

    View Slide

  48. THANK YOU!

    View Slide