$30 off During Our Annual Pro Sale. View Details »

サーバサイドKotlinでGraphQLをやってみよう - Kotlin Fest 2019 - / Server side Kotlin + GraphQL

Shiraji
August 24, 2019

サーバサイドKotlinでGraphQLをやってみよう - Kotlin Fest 2019 - / Server side Kotlin + GraphQL

Shiraji

August 24, 2019
Tweet

More Decks by Shiraji

Other Decks in Programming

Transcript

  1. αʔόαΠυKotlinͰ

    GraphQLΛ΍ͬͯΈΑ͏
    ͠Β͡

    View Slide

  2. Who am I?
    • Kotlin + GraphQL 1+ year

    • Open Source kotlin-graphql-sample

    • Love Kotlin

    • Works for Ubie, Inc
    @shiraji @shiraj_i

    View Slide

  3. ςΫϊϩδʔͰਓʑΛద੾ͳҩྍʹҊ಺͢Δ

    View Slide

  4. Kotlin Fest Organizer & Speakers
    We are hiring!!! https://ubie.life/

    View Slide

  5. ͜͜ʹ͍Δਓͨͪ
    • KotlinΛ৮ͬͨ͜ͱ͕͋Δ

    • αʔόαΠυKotlinɺGraphQLʹڵຯ͕͋Δ

    • GET/POST΍ϨεϙϯείʔυͳͲͷHTTPͷجૅతͳ஌͕ࣝ͋Δ

    • ηογϣϯதʹ൓Ԡͯ͘͠ΕΔ

    View Slide

  6. ͜͜ʹ͍Δਓͨͪ
    • KotlinΛ৮ͬͨ͜ͱ͕͋Δ

    • αʔόαΠυKotlinɺGraphQLʹڵຯ͕͋Δ

    • GET/POST΍ϨεϙϯείʔυͳͲͷHTTPͷجૅతͳ஌͕ࣝ͋Δ

    • ηογϣϯதʹ൓Ԡͯ͘͠ΕΔ

    View Slide

  7. ࣭ͬͦ͘͞໰
    αʔόαΠυKotlin΍ͬͨ͜ͱ͋Δਓʔʁ

    View Slide

  8. ࣭໰2
    αʔόαΠυKotlin+GraphQL΍ͬͨ͜ͱ͋Δਓʔʁ

    View Slide

  9. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  10. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  11. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    Ϣʔβͷ໊લҰཡͷAPI͕ཉ͍͠

    View Slide

  12. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    {

    [

    "name": “Nagasawa Taro”

    ],

    [

    "name": “Isogai Yoshinori”

    ]

    }

    View Slide

  13. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    ͜ͷOSͰ͸first name͚ͩཉ͍͠

    View Slide

  14. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    {

    [

    “first_name”: “Taro”

    ],

    [

    “first_name": “Yoshinori”

    ]

    }

    View Slide

  15. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    ͜ͷαΠτ͸

    TwitterΞΧ΢ϯτ͕ཉ͍͠

    View Slide

  16. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    {

    [

    “twitter”: “ngsw_taro”

    ],

    [

    “twitter": “shiraji”

    ]

    }

    View Slide

  17. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    ͜ͷAPI͸icon͚ͩͰྑ͍

    View Slide

  18. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    {

    [

    “icon”: “https://…”

    ],

    [

    “icon”: “https://…”

    ]

    }

    View Slide

  19. ɾɾɾͷલʹɺ͜Μͳܦݧ͋Γ·ͤΜ͔ʁ
    {

    [

    "name": “Nagasawa Taro”,

    “first_name”: “Taro”,

    “twitter”: “ngsw_taro”,

    “icon”: “https://…”

    ]

    }

    View Slide

  20. GraphQLͱ͸Կʁ
    • A query language for your API

    • εΩʔϚͱΫΤϦ

    • GraphQL Fundation

    • OSS

    • e.g. GitHub API v4

    View Slide

  21. εΩʔϚͱΫΤϦ
    type User {

    id: ID!

    name: String!

    account: String

    }

    View Slide

  22. εΩʔϚͱΫΤϦ
    type Query {

    user(id: ID!) : User

    }

    type Mutation {

    createUser(name: String!)

    }
    type User {

    id: ID!

    name: String!

    account: String

    }

    View Slide

  23. εΩʔϚͱΫΤϦ
    query {

    user(id: "aaa") {

    id

    name

    account

    }

    }

    View Slide

  24. εΩʔϚͱΫΤϦ
    type Query {

    user(id: ID!) : User

    }
    type User {

    id: ID!

    name: String!

    account: String

    }

    View Slide

  25. εΩʔϚͱΫΤϦ
    type Query {

    user(id: ID! )
    a
    : User

    }
    type User {a

    id: ID!

    name: String!

    account: String

    }a

    View Slide

  26. εΩʔϚͱΫΤϦ
    query {

    user(id: "aaa" )
    a
    {a

    id

    name

    account

    }a

    }

    View Slide

  27. εΩʔϚͱΫΤϦ
    {

    "data" : {a

    "id": "aaa",

    "name": "ү֋Ղయ",

    "account": "shiraji"

    }a

    }

    View Slide

  28. εΩʔϚͱΫΤϦ
    query {

    user(id: "aaa") {ccc

    id

    name

    account

    }a

    }b

    View Slide

  29. εΩʔϚͱΫΤϦ
    query {

    user(id: "aaa") {ccc

    id

    name

    }a

    }b

    View Slide

  30. εΩʔϚͱΫΤϦ
    {

    "data" : {ccc

    "id": "aaa",

    "name": "ү֋Ղయ"

    }a

    }b

    View Slide

  31. εΩʔϚ
    type Query {

    users: [User!]!

    }

    type User {

    id: ID!

    name: String!

    first_name: String!

    twitter: String!

    icon: String!

    }

    View Slide

  32. ΫΤϦ
    query user() {

    name

    }
    query user() {

    first_name

    }
    query user() {

    twitter

    }
    query user() {

    Id

    }
    query user() {

    Icon

    }

    View Slide

  33. Ͳ͏͍͏ͱ͜ΖͰ࢖͏ͱྑ͍͔ʁ
    • FE/BEෳ਺ਓ͕։ൃΛ୲౰

    • ϦϞʔτͳͲର໘ରԠ͕Ͱ͖ͳ͍

    • ରԠ͢ΔλΠϛϯάʹ͕࣌ࠩ͋Δ

    View Slide

  34. ࣄྫ Ubie, Inc

    View Slide

  35. ࣄྫ Ubie, Inc

    View Slide

  36. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  37. kotlin-graphql-sample
    dependencies {

    implementation("org.springframework.boot:spring-boot-starter")

    implementation("com.graphql-java-kickstart:graphql-spring-boot-starter")

    implementation("com.graphql-java-kickstart:graphiql-spring-boot-starter")

    implementation(“com.graphql-java-kickstart:graphql-java-tools")

    implementation("org.springframework.boot:spring-boot-starter-jdbc")

    }

    View Slide

  38. εΩʔϚ
    type Drug {

    id: String!

    name: String!

    yjCode: String!

    description: String

    }
    type Disease {

    icd: String!

    name: String!

    }

    View Slide

  39. εΩʔϚ
    data class Drug(

    val id: String,

    val name: String,

    val yjCode: String,

    val description: String?

    )
    data class Disease(

    val icd: String,

    val name: String

    )

    View Slide

  40. Query
    type Query {

    drug(id: String!) : Drug

    drugs(yjCode: String!) : [Drug!]!

    diseases(icd: String!) : [Disease!]!

    }

    View Slide

  41. GraphQLQueryResolver
    • GraphQLQueryResolverΛܧঝ

    • ΞϓϦέʔγϣϯ಺ͷ͢΂ͯͷܧঝͨ͠ΫϥεΛࢀর

    • ϝιου໊ɺҾ਺ɺ໭Γ஋ͰϚοϐϯά

    • ϝιου໊͸getterͰ΋OK

    View Slide

  42. εΩʔϚ
    type Query {a

    drugs(yjCode: String!) : [ Drug !]!

    }a

    View Slide

  43. εΩʔϚ
    @Component

    class DrugQueryResolver : GraphQL Query Resolver {a

    fun drugs(yjCode: String
    !
    ) : List< Drug > = TODO()

    }a

    View Slide

  44. εΩʔϚ
    @Component

    class DrugQueryResolver : GraphQL Query Resolver {

    fun drugs(yjCode: String
    !
    ) : List< Drug > = TODO()

    }

    View Slide

  45. Query
    type Query {

    drug(id: String! )
    a
    :
    a
    Drug

    drugs(yjCode: String! )
    a
    :
    a
    [Drug!]!

    diseases(icd: String! )
    a
    :
    a
    [Disease!]!

    }

    View Slide

  46. Query
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug(id: String )
    a
    :
    a
    Drug? = TODO()

    fun drugs(yjCode: String )
    a
    :
    a
    List< Drug > = TODO()

    }

    @Component

    class DiseaseQueryResolver : GraphQLQueryResolver {

    fun diseases(icd: String )
    a
    :
    a
    List< Disease > = TODO()

    }

    View Slide

  47. Request

    View Slide

  48. Response

    View Slide

  49. ෮श
    • εΩʔϚ͕ॏཁ

    • type͕͋Δ

    • KotlinͰ͸data classͰදݱͰ͖Δ

    • type Query(ͱMutation)͕ಛघ

    • GraphQLQueryResolverͷϝιουʹ
    Ϛοϐϯά͞ΕΔ
    type Drug {

    id: ID!

    name: String!

    description: String

    }

    type Query {

    drugs(code: String) : [Drug]!

    }

    View Slide

  50. ෮श໰୊
    type User {

    name: String

    }
    data class User(

    val name: String

    )

    data class User(

    val name: String?

    )
    data class User(

    val name: List

    )

    View Slide

  51. ͜͜ʹ͍Δਓͨͪ
    • KotlinΛ৮ͬͨ͜ͱ͕͋Δ

    • αʔόαΠυKotlinɺGraphQLʹڵຯ͕͋Δ

    • GET/POST΍ϨεϙϯείʔυͳͲͷHTTPͷجૅతͳ஌͕ࣝ͋Δ

    • ηογϣϯதʹ൓Ԡͯ͘͠ΕΔ

    View Slide

  52. ෮श໰୊
    type User {

    name: String

    }
    data class User(

    val name: String

    )

    data class User(

    val name: String?

    )
    data class User(

    val name: List

    )

    View Slide

  53. typeͷؔ܎

    View Slide

  54. typeͷؔ܎
    type Drug {

    id: ID!

    name: String!

    yjCode: String!

    description: String

    kinkiDiseases: [Disease!]!

    }

    type Disease {

    icd: String!

    name: String!

    kinkiDrugs: [Drug!]!

    }
    data class Drug(

    val id: String,

    val name: String,

    val yjCode: String,

    val description: String?

    )

    data class Disease(

    val icd: String,

    val name: String

    )

    View Slide

  55. GraphQLResolver
    • GraphQLResolverΛܧঝ

    • ܕม਺͕ϝιουͷҾ਺

    • ͋ͱ͸GraphQLQueryResolverͱಉ͡

    View Slide

  56. typeͷؔ܎
    type Drug {



    kinkiDiseases: [Disease!]!

    }
    Drug

    View Slide

  57. typeͷؔ܎
    class DrugResolver : GraphQLResolver< Drug > {

    fun kinkiDiseases (drug: Drug): List< Disease > {

    TODO()

    }

    }

    View Slide

  58. Kotlinݺͼग़͞ΕΔॱ൪

    View Slide

  59. Kotlinݺͼग़͞ΕΔॱ൪

    View Slide

  60. Kotlinݺͼग़͞ΕΔॱ൪

    View Slide

  61. type Drug {

    id: ID!

    name: String!

    yjCode: String!

    description: String

    kinkiDiseases: [Disease!]!

    }
    data class Drug(

    val id: String,

    val name: String,

    val yjCode: String,

    val description: String?

    )
    εΩʔϚͱKotlinͷϚοϐϯά·ͱΊ

    View Slide

  62. type Drug {

    id: ID!

    name: String!

    yjCode: String!

    description: String

    kinkiDiseases: [Disease!]!

    }
    class DrugResolver : GraphQLResolver {

    fun kinkiDiseases(drug: Drug): List {…}

    }
    εΩʔϚͱKotlinͷϚοϐϯά·ͱΊ

    View Slide

  63. type Drug {

    id: ID!

    name: String!

    yjCode: String!

    description: String

    kinkiDiseases: [Disease!]!

    }
    data class Drug(

    val id: String,

    val name: String,

    val yjCode: String,

    val description: String?

    )
    class DrugResolver : GraphQLResolver {

    fun kinkiDiseases(drug: Drug): List {…}

    }
    εΩʔϚͱKotlinͷϚοϐϯά·ͱΊ

    View Slide

  64. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  65. • mock͢Ε͹OK
    Kotlin+GraphQLͷςετ
    Ҏ্ɻ

    View Slide

  66. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  67. Kotlin+GraphQLͷೝূ
    • ೝূํ๏͸͍͔ͭ͋͘Δ

    • Auth HeaderͷtokenͰೝূ͢Δํ๏Λ঺հ

    • Authorization: Bearer

    View Slide

  68. DataFetchingEnvironment
    • ֤छResolver͔ΒΞΫηεՄೳ

    • Fetch͢΂͖৘ใ

    • ϑΟʔϧυͷҾ਺

    • ϑΟʔϧυͷ਌ͷ৘ใ

    View Slide

  69. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug(id: String): Drug? {

    TODO()

    }a

    }a

    View Slide

  70. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug( id: String, environment: DataFetchingEnvironment): Drug? {

    TODO()

    }a

    }a

    View Slide

  71. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug( environment: DataFetchingEnvironment, id: String): Drug? {

    TODO()

    }a

    }a
    ເͷ࿩Ͱ͢

    View Slide

  72. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun DataFetchingEnvironment. drug( id: String): Drug? {

    TODO()

    }a

    }a
    ເͷ࿩Ͱ͢

    View Slide

  73. Context
    • DataFetchingEnvironment͔ΒContextʹΞΫηεͰ͖Δ

    • ΫΤϦड͚औΓʙऴΘΓ·Ͱੜ͖Δ

    • ͲΜͳ஋Ͱ΋OK

    • GraphQLContextΛܧঝ͢Δ

    • ެ͕͓ࣜ͢͢Ί

    View Slide

  74. Context
    class AuthContext(httpServletRequest: HttpServletRequest, val userId: Long?)

    : GraphQLContext(httpServletRequest)

    View Slide

  75. GraphQLContextBuilder
    @Bean

    fun contextBuilder(): GraphQLContextBuilder {

    return object : DefaultGraphQLContextBuilder() {

    }b

    }a

    View Slide

  76. GraphQLContextBuilder
    @Bean

    fun contextBuilder(): GraphQLContextBuilder {

    return object : DefaultGraphQLContextBuilder() {

    override fun build(

    httpServletRequest: HttpServletRequest,

    httpServletResponse: HttpServletResponse

    ): GraphQLContext {

    }c

    }b

    }a

    View Slide

  77. GraphQLContextBuilder
    @Bean

    fun contextBuilder(): GraphQLContextBuilder {

    return object : DefaultGraphQLContextBuilder() {

    override fun build(

    httpServletRequest: HttpServletRequest,

    httpServletResponse: HttpServletResponse

    ): GraphQLContext {

    val authHeader = httpServletRequest.getHeader(“Authorization")

    }c

    }b

    }a

    View Slide

  78. GraphQLContextBuilder
    @Bean

    fun contextBuilder(): GraphQLContextBuilder {

    return object : DefaultGraphQLContextBuilder() {

    override fun build(

    httpServletRequest: HttpServletRequest,

    httpServletResponse: HttpServletResponse

    ): GraphQLContext {

    val authHeader = httpServletRequest.getHeader("Authorization")

    val token = authHeader?.removePrefix("Bearer ")

    val userId = TODO() // ͳΜͱ͔͢Δ

    }c

    }b

    }a

    View Slide

  79. GraphQLContextBuilder
    @Bean

    fun contextBuilder(): GraphQLContextBuilder {

    return object : DefaultGraphQLContextBuilder() {

    override fun build(

    httpServletRequest: HttpServletRequest,

    httpServletResponse: HttpServletResponse

    ): GraphQLContext {

    val authHeader = httpServletRequest.getHeader("Authorization")

    val token = authHeader?.removePrefix("Bearer ")

    val userId = TODO()

    return AuthContext(httpServletRequest, userId)

    }c

    }b

    }a

    View Slide

  80. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug(id: String, environment: DataFetchingEnvironment): Drug? {

    TODO(“DrugΛऔಘ͢Δॲཧ”)

    }b

    }a

    View Slide

  81. DataFetchingEnvironment
    @Component

    class DrugQueryResolver : GraphQLQueryResolver {

    fun drug(id: String, environment: DataFetchingEnvironment): Drug? {

    environment.getContext().userId

    ?: throw Exception(“ೝূ͞Εͯͳ͍Α”)

    TODO(“DrugΛऔಘ͢Δॲཧ”)

    }b

    }a

    View Slide

  82. Kotlin + GraphQLೝূ·ͱΊ
    • DataFetchingEnvironment͸֤छResolverͰΞΫηεՄೳ

    • ಠࣗͷContextΛ࡞੒Մೳ

    • GraphQLContextΛܧঝ͢Δ

    • Context͸GraphQLContextBuilder#build಺Ͱੜ੒

    • Contextʹೝূ৘ใ࣋ͨͤͯResolver಺Ͱೝূ͢Δ

    View Slide

  83. ࿩͢͜ͱ
    • GraphQLͱ͸Կʁ

    • Kotlin+GraphQLͷίʔυͷྲྀΕ

    • Kotlin+GraphQLͷςετ

    • Kotlin+GraphQLͷೝূ

    • Kotlin+GraphQLͷपลπʔϧ

    View Slide

  84. GraphiQL
    • ϒϥ΢βΛGraphQLͷΫΤϦฤूIDEʹ

    • dependenciesʹॻ͚͹ɺαʔό্ཱͪ͛Ε͹ಈ͘ʂ
    dependencies {

    implementation("com.graphql-java-kickstart:graphiql-spring-boot-starter")

    }

    View Slide

  85. σϞ

    View Slide

  86. Altair
    • GraphiQLͱ΄΅ಉ͡

    • HeaderͷઃఆΛϒϥ΢β্Ͱ؆୯ʹग़དྷΔ
    dependencies {

    implementation("com.graphql-java-kickstart:altair-spring-boot-starter")

    }

    View Slide

  87. apollo-android
    • GraphQLΛ࢖͏ଆ

    • Androidͱॻ͔Ε͍ͯΔ͚ͲɺJavaϕʔεͰར༻Մೳ

    View Slide

  88. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide