Successfully reported this slideshow.
Your SlideShare is downloading. ×

GraphQL and Groovy

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 75 Ad

More Related Content

Recently uploaded (20)

Advertisement

GraphQL and Groovy

  1. 1. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL AND GROOVYGRAPHQL AND GROOVYGRAPHQL AND GROOVYGRAPHQL AND GROOVYGRAPHQL AND GROOVYGRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVY GRAPHQL AND GROOVYGRAPHQL AND GROOVY @marioggar 1
  2. 2. #greachConf @marioggar © Mario Garcia 2017 ABOUT ME Name Mario Garcia You can find me: https://twitter.com/marioggar https://github.com/mariogarcia 2 . 1
  3. 3. #greachConf @marioggar © Mario Garcia 2017 PROUD MEMBER OF…​ 2 . 2
  4. 4. #greachConf @marioggar © Mario Garcia 2017 WORKING AT KALEIDOS 2 . 3
  5. 5. #greachConf @marioggar © Mario Garcia 2017 BUT A GREAT FAMILY 2 . 4
  6. 6. #greachConf @marioggar © Mario Garcia 2017 LET ME TELL YOU WHY YOU’RE HERE…​ I’ve heard GraphQL is the next big thing If I do one more REST app I’ll kill myself I didn’t find any other interesting talk Whatever it is…​ 3 . 1
  7. 7. #greachConf @marioggar © Mario Garcia 2017 3 . 2
  8. 8. #greachConf @marioggar © Mario Garcia 2017 SUMMARY 4 . 1
  9. 9. #greachConf @marioggar © Mario Garcia 2017 GraphQL overview GraphQL types query language GraphQL + JVM + HTTP Conclusions 4 . 2
  10. 10. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL OVERVIEW 5 . 1
  11. 11. #greachConf @marioggar © Mario Garcia 2017 WHAT IS GRAPHQL Is a query language Is also a server-side runtime spec It uses a type system to define those queries 5 . 2
  12. 12. #greachConf @marioggar © Mario Garcia 2017 WHAT IS NOT GRAPHQL Is not a web framework Is not about HTTP And definitely, definitely, definitely…​ GraphQL is not REST 5 . 3
  13. 13. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL VS REST 5 . 4
  14. 14. #greachConf @marioggar © Mario Garcia 2017 WHY WE COULD WANT TO MOVE TO GRAPHQL ? 5 . 5
  15. 15. #greachConf @marioggar © Mario Garcia 2017 FIRST OF ALL While REST is an architectural concept GraphQL is just a query language 5 . 6
  16. 16. #greachConf @marioggar © Mario Garcia 2017 DIFFERENCES Resources vs Queries Rest: 1 URI =⇒ 1 resource GraphQL: 1 URI =⇒ n dataset Application layer Rest == HTTP GraphQL is not tied to any specific protocol Front-End friendly Rest: Back end is the king ...and the bottleneck 5 . 7
  17. 17. #greachConf @marioggar © Mario Garcia 2017 NO PROBLEM. I'LL SEE WHAT I CAN DO 5 . 8
  18. 18. #greachConf @marioggar © Mario Garcia 2017 THE CHALLENGE I want to expose all James Bond films information Users will ONLY use web browsers...FOR NOW BUT we have to be ready for mobile AT SOME POINT 5 . 9
  19. 19. #greachConf @marioggar © Mario Garcia 2017 WHAT DO WE DO ? We build up 1 API endpoint Only targets 1 device Still we can create a couple of views for the same data 5 . 10
  20. 20. #greachConf @marioggar © Mario Garcia 2017 THEN SHIT HAPPENS! 5 . 11
  21. 21. #greachConf @marioggar © Mario Garcia 2017 AND NORMALLY GETS WORST Users want to see A, B, and C in user home Front end could reuse views and/or aggregate calls still may not be enough and they will start asking back-end to do more…​ and more …​ and more…​ 5 . 12
  22. 22. #greachConf @marioggar © Mario Garcia 2017 5 . 13
  23. 23. #greachConf @marioggar © Mario Garcia 2017 THEN YOU REMEMBER THAT…​ ONLY means in addition FOR NOW means within the next two weeks BUT means winter is coming! and of course…​AT SOME POINT means probably next week 5 . 14
  24. 24. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL + HTTP TO THE RESCUE! 5 . 15
  25. 25. #greachConf @marioggar © Mario Garcia 2017 5 . 16
  26. 26. #greachConf @marioggar © Mario Garcia 2017 WHAT CHANGED ? GraphQL HTTP endpoint as a common query interface Therefore a lot more flexibility for front end Your REST/NOT-REST microservices will be easier to maintain Will be easier to keep one single responsability in each one of them 5 . 17
  27. 27. #greachConf @marioggar © Mario Garcia 2017 EXECUTING QUERIES 6 . 1
  28. 28. #greachConf @marioggar © Mario Garcia 2017 STEPS TO EXECUTE A QUERY Define TYPES Define QUERIES Execute queries against schema 6 . 2
  29. 29. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE 6 . 3
  30. 30. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE: SCHEMA type Film { title: !String year: Int } type Queries { lastFilm: Film filmByYear(year: Int): Film } schema { query: Queries } http://facebook.github.io/graphql/ 6 . 4
  31. 31. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE: TYPES Client CAN add/omit as many optional fields as it wants Client MUST add mandatory fields in the query type Film { title: !String year: Int } 6 . 5
  32. 32. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE : QUERIES Queries always use types or scalars Queries may have arguments type Queries { lastFilm: Film filmByYear(year: Int): Film } 6 . 6
  33. 33. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE : EXECUTE QUERY query: "give me the last James Bond film with its title result: "SPECTRE" { lastFilm { title } } { "data": { "lastFilm": { "title": "SPECTRE" } } } 6 . 7
  34. 34. #greachConf @marioggar © Mario Garcia 2017 LITTLE BIT CLOSER query 1. lastFilm: Is the query I’m interested in 2. title: Is a specific field in the return type (Film) { lastFilm { (1) title (2) } } 6 . 8
  35. 35. #greachConf @marioggar © Mario Garcia 2017 VALIDATION title is mandatory invalid query type Film { title: !String year: Int } { lastFilm } 6 . 9
  36. 36. #greachConf @marioggar © Mario Garcia 2017 6 . 10
  37. 37. #greachConf @marioggar © Mario Garcia 2017 JVM LIBRARIES OUT THERE! GraphQL-Java https://github.com/graphql-java/graphql-java 6 . 11
  38. 38. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE REVISITED: TYPES type Film { title: !String year: Int } GraphQLObjectType.newObject() .name("Film") .field(newFieldDefinition() .type(GraphQLString) .name("title")) .field(newFieldDefinition() .type(GraphQLInt) .name("year")) .build(); 6 . 12
  39. 39. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE REVISITED: QUERIES type Queries { lastFilm: Film filmByYear(year: Int): Film } schema { query: Queries } GraphQLObjectType lastFilm = GraphQLObjectType.newObject() .name("Queries") .field(newFieldDefinition() .type(filmType) .name("lastFilm") .dataFetcher(Queries::findLastFilm)) .build(); return GraphQLSchema .newSchema() .query(lastFilm) .build(); 6 . 13
  40. 40. #greachConf @marioggar © Mario Garcia 2017 DATA FETCHER Functional Interface graphql.schema.DataFetcher If using JDK could use method reference If using Groovy Closures FTW If using Groovy w Parrot → Both o/ 6 . 14
  41. 41. #greachConf @marioggar © Mario Garcia 2017 FIRST EXAMPLE REVISITED: EXECUTION 1. schema: query + types definition 2. query: query string 3. context: helpful for adding metadata (e.g. authorization) 4. variables: if the query has any Map<String,Object> result = new GraphQL(schema) (1) .execute(query, (2) null, (3) "") (4) .getData() as Map<String,Object> 6 . 15
  42. 42. #greachConf @marioggar © Mario Garcia 2017 TOO MUCH JAVA CODE…​ 6 . 16
  43. 43. #greachConf @marioggar © Mario Garcia 2017 6 . 17
  44. 44. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL DSL (GQL) DSL over GraphQL-Java Still alpha Feeback is very welcome :) https://github.com/grooviter/gql 6 . 18
  45. 45. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: TYPES type Film { title: !String year: Int } DSL.type('Film') { field('title') { type nonNull(GraphQLString) } field('something', GraphQLBoolean) field('year') { description 'release date' type GraphQLString } } 6 . 19
  46. 46. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: TYPES (II) vs GraphQLObjectType.newObject() .name("Film") .field(newFieldDefinition() .type(GraphQLString) .name("title")) .field(newFieldDefinition() .type(GraphQLInt) .name("year")) .build(); DSL.type('Film') { field('title') { type nonNull(GraphQLString) } field('something', GraphQLBoolean) field('year') { description 'release date' type GraphQLString } } 6 . 20
  47. 47. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: QUERIES type Queries { lastFilm: Film filmByYear(year: Int): Film } schema { query: Queries } return DSL.schema { query('Queries') { field('lastFilm') { type Schema.FilmType fetcher Queries.&findLastFilm } field('byYear') { type Schema.FilmType fetcher Queries.&findByYear argument('year') { type GraphQLString } } } } 6 . 21
  48. 48. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: QUERIES (II) vs GraphQLObjectType lastFilm = GraphQLObjectType.newObject() .name("Queries") .field(newFieldDefinition() .type(filmType) .name("lastFilm") .dataFetcher(Queries::findLastFilm)) .build(); return GraphQLSchema .newSchema() .query(lastFilm) .build(); return DSL.schema { query('Queries') { field('lastFilm') { type Schema.FilmType fetcher Queries.&findLastFilm } field('byYear') { type Schema.FilmType fetcher Queries.&findByYear argument('year') { type GraphQLString } } 6 . 22
  49. 49. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: QUERY EXECUTION yields def result = DSL .execute(schema, queryString) .data as Map<String,Object> { lastFilm: { year: 2015, title: 'SPECTRE' } } 6 . 23
  50. 50. #greachConf @marioggar © Mario Garcia 2017 GROOVY TIME: QUERY EXECUTION (II) vs Map<String,Object> result = new GraphQL(schema) (1) .execute(query, (2) null, (3) "") (4) .getData() as Map<String,Object> def result = DSL .execute(schema, queryString) .data as Map<String,Object> 6 . 24
  51. 51. #greachConf @marioggar © Mario Garcia 2017 QUERIES WITH ARGUMENTS 6 . 25
  52. 52. #greachConf @marioggar © Mario Garcia 2017 WHO KNOWS THE TITLE OF 1962 ? query query execution queryString = ''' query FindBondFilmByYear($year: String){ byYear(year: $year) { year title } } ''' Map<String,Object> result = DSL .execute(schema, queryString, [year: year]) .data 6 . 26
  53. 53. #greachConf @marioggar © Mario Garcia 2017 DR. NO [byYear: [ title: 'DR. NO', year: "1962" ] ] 6 . 27
  54. 54. #greachConf @marioggar © Mario Garcia 2017 NOW…​ 6 . 28
  55. 55. #greachConf @marioggar © Mario Garcia 2017 WOULDN’T IT COOL IF I EXPOSE THIS TO THE WORLD ? 6 . 29
  56. 56. #greachConf @marioggar © Mario Garcia 2017 HTTP + GRAPHQL 7 . 1
  57. 57. #greachConf @marioggar © Mario Garcia 2017 RATPACK + GRAPHQL 7 . 2
  58. 58. #greachConf @marioggar © Mario Garcia 2017 TECHNOLOGIES USED Ratpack GraphQL-java GQL GraphiQL 7 . 3
  59. 59. #greachConf @marioggar © Mario Garcia 2017 FULL FILM TYPE And it fits in the slide!! static final GraphQLObjectType Film = DSL.type('Film') { field 'title' , nonNull(GraphQLString) field 'year' , GraphQLInt field 'directedBy' , GraphQLString field 'bond' , GraphQLString field 'themeSong' , list(ThemeSong) field 'bondGirls' , list(BondGirl) field 'villains' , list(Villain) field 'counterparts', list(CounterPart) field 'gadgets' , list(GraphQLString) field 'vehicles' , list(GraphQLString) } 7 . 4
  60. 60. #greachConf @marioggar © Mario Garcia 2017 QUERIES return DSL.schema { query('Queries') { field('lastFilm') { type Schema.Film fetcher Queries.&findLastFilm } field('byYear') { type Schema.Film fetcher Queries.&findByYear argument('year') { type GraphQLString } } field('byBondActorNameLike') { type list(Schema.Film) fetcher Queries.&byBondActorNameLike argument('name') { type GraphQLString } } } } 7 . 5
  61. 61. #greachConf @marioggar © Mario Garcia 2017 RATPACK HANDLER class GraphQLHandler implements Handler { @Inject GraphQLSchema schema @Override void handle(final Context ctx) { def payload = ctx.get(Map) // JSON request => Map Blocking.get { DSL.execute(schema, "${payload.query}", payload.variables as Map<String,Object>) }.then { ExecutionResult result -> def response = [data: result.errors ?: result.data] ctx.render json(response) } } } 7 . 6
  62. 62. #greachConf @marioggar © Mario Garcia 2017 URI MAPPING 1. GraphQL endpoint 2. GraphiQL web console handlers { prefix('graphql') { (1) all(createBindingHandler(Map)) post(GraphQLHandler) } files { (2) dir('static').indexFiles('index.html') } } 7 . 7
  63. 63. #greachConf @marioggar © Mario Garcia 2017 SHOWTIME! query UserHome($actor: String, $year: String) { latest: lastFilm { title year directedBy bond } whenIwasBorn: byYear(year: $year) { title } favouriteActorMovies: byBondActorNameLike(name: $actor) { title year bond } } 7 . 8
  64. 64. #greachConf @marioggar © Mario Garcia 2017 A WORD ON QUERIES & MUTATIONS Queries are supposed to be able to be batched Queries are supposed to be computed in parallel Mutations are supposed to run sequentially 7 . 9
  65. 65. #greachConf @marioggar © Mario Garcia 2017 GRAILS + RELAY 7 . 10
  66. 66. #greachConf @marioggar © Mario Garcia 2017 RELAY ? Good GraphQL practices implemented in a JS library https://facebook.github.io/relay/ 7 . 11
  67. 67. #greachConf @marioggar © Mario Garcia 2017 RELAY How to handle pagination How to handle ids HTTP recommended features …​ http://graphql.org/learn/best-practices/ 7 . 12
  68. 68. #greachConf @marioggar © Mario Garcia 2017 GORM GRAPHQL Plugin Grails 3 https://github.com/mrcirillo/relay-gorm-connector 7 . 13
  69. 69. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL SCHEMA @RelayType(description='An optional description of a film') class Film { @RelayField(description='An optional description of name') String title String year String bond } 7 . 14
  70. 70. #greachConf @marioggar © Mario Garcia 2017 GRAILS URLMAPPINGS post "/graphql"(controller: "graph") 7 . 15
  71. 71. #greachConf @marioggar © Mario Garcia 2017 GRAILS CONTROLLER class GraphController { def relayService // provided by plugin def index() { def query = request.JSON.query.toString() def vars = request.JSON.variables def result = relayService.query(query, null, vars?:[:]) render(result as JSON) } } 7 . 16
  72. 72. #greachConf @marioggar © Mario Garcia 2017 GRAPHQL BEST PRACTICES HINT: ID HASHING Instead of passing 1 use a hash like hagghsXy== def idString = RelayHelpers.toGlobalId("Film", film.id.toString()) def query = """ query { node(id: "$idString") { ... on Film { title } } } """ 7 . 17
  73. 73. #greachConf @marioggar © Mario Garcia 2017 CONCLUSIONS Is not GraphQL instead of REST Is about GraphQL over your existent services A great improvement from the business point of view Your front end workmates will love you 8 . 1
  74. 74. #greachConf @marioggar © Mario Garcia 2017 THANK YOU! 8 . 2
  75. 75. #greachConf @marioggar © Mario Garcia 2017 QUESTIONS & ANSWERS 9

×