GraphQL 101

506 views

Published on

GraphQL session by Paul Withers and Philippe Riand at Engage 2017, Antwerp

Published in: Software
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
506
On SlideShare
0
From Embeds
0
Number of Embeds
340
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

GraphQL 101

  1. 1. GraphQL 101 1#engageug
  2. 2. Paul Withers ICS Consultant, Intec Systems Ltd IBM Champion since 2011 OpenNTF Board Member WWS Java SDK developer 2#engageug
  3. 3. Philippe Riand CTO of Trilog Group & Darwino Inc. Former application development chief architect for IBM Collaboration Services Chief architect, and inventor, of IBM Domino XPages 3#engageug
  4. 4. The Problem With REST Multiple calls required • “Joins” are consumer’s responsibility • May result in a large number of REST calls –> Latency is multiplied by the number of calls -> sequential behaviour Provider-driven • Consumer gets what they get, needs to parse accordingly Versions • Changes typically require version increment • May affect consumer’s application object model Validation • Request cannot be validated prior to submission 4#engageug
  5. 5. Enter GraphQL 5#engageug
  6. 6. What Is GraphQL? Created by Facebook 2012 Specification for standard began 2015 Query language • Not database architecture • Not programming language • A modern way to expose your API and give your clients more Control on what they get 6#engageug
  7. 7. Why GraphQL? Consumer-driven • Returns what the client asks for and no more! Hierarchical • Query and response are both JSON, in same hierarchical structure Strongly Typed • GraphQL type structure ensures query can be tested for syntactical correctness and validity before execution Introspective • GraphQL language can be used to query the type structure 7#engageug
  8. 8. GraphQL • Open source in-browser IDE https://github.com/graphql/graphiql • Build validated and syntactically correct queries / mutations and fragments • Define query variables • Run queries and browse response • Run a query to introspect schema • Drill down through schema documentation • Visualizer tools also available http://nathanrandal.com/graphql-visualizer/ 8#engageug
  9. 9. GraphiQL 9#engageug
  10. 10. GraphQL and Watson Work Services • Documentation online https://workspace.ibm.com/developer/docs • GraphiQL tool for WWS https://workspace.ibm.com/graphql • Must be authenticated in browser to Watson Workspace first! • Queries run as user, not application • Some queries are not available to applications • Additional REST endpoints exist (e.g. authentication, focus, photos) • These are usually version-based, e.g. …/v1/… 10#engageug
  11. 11. GraphQL Queries (GET Requests) 11#engageug
  12. 12. GraphQL Query Structure Query can have operation name, optional if only one query Query object has fields for things that can be returned Fields may take (or require) arguments • Arguments have a type (String, Int, ID etc) • See GraphQL documentation for more details • Required arguments have “!” after the type in documentation (e.g. space(id:ID!) • Argument values may be literal or map to variables 12#engageug
  13. 13. GraphQL Query Structure Variables • Passed as an argument of the operation name • Format is “$VariableName: Type” (e.g. $FIRST: Int) • Passed to value of an argument in the operation • Declared as a separate JSON object • Key is variable name as a String • Value is variable value • Validated in GraphiQL IDE, like rest of query 13#engageug
  14. 14. GraphQL Query Structure Fields may have an alias • Format is “alias: field” • Allows query to retrieve multiple result objects of same field type • In response, field type is replaced with alias Fields will themselves have fields and/or objects to return 14#engageug
  15. 15. GraphQL Query Structure Queries on lists may return lots of objects “Slice” using first and last Return pageInfo object to get cursor Pass cursor back to query using before or after 15#engageug
  16. 16. GraphQL Query Structure Fragments can be included to improve readability of complex queries • Defined as separate JSON object • Format is “fragment fragmentName on type” • Allows fields to be defined and validated inline • Used with format “…fragmentName” Schema may return an interface or union type • Inline fragment may be required to act differently depending on actual implementation from interface • Format is “… on type” • Not used in WWS, see GraphQL documentation for examples 16#engageug
  17. 17. Query Fragments 17#engageug
  18. 18. GraphQL Query Structure Directives allow dynamic manipulation of the query based on variables • @include(if: Boolean) • @skip(if: Boolean) 18#engageug
  19. 19. GraphQL MUTATIONS (PUT, POST, PATCH, DELETE Requests) 19#engageug
  20. 20. GraphQL Mutations Mutation can have an operation name Declares the field to set (function) Pass an input object to the field Returns a type • May just be a scalar (e.g. true / false) • May be an object (e.g. a space) • If an object, that can be queried, as in a query Can pass multiple fields (processed sequentially) 20#engageug
  21. 21. GraphQL Subscriptions Subscription allows clients to receive updates Declares the field to subscribe to Pass an input object to the field, including subscription id Nothing yet implemented for this in Watson Work Services 21#engageug
  22. 22. Introspecting GraphQL Schema GraphQL schema can be introspected with GraphQL query! • __schema queries the schema • __type introspects a specific type • kind introspects field type • If NON_NULL, ofType returns its actual type “It’s GraphQL queries all the way down” 22#engageug
  23. 23. GraphQL – Real World Implementations - Facebook - Watson Works Services - Darwino (OpenSource Project hosted on OpenNTF and darwino.org) - Connections Pink 23#engageug
  24. 24. Darwino GraphQL Implementation Darwino is providing a set of open source libraries for both consumers and producers of GraphQL The libraries are part of the Darwino core code but hosted on OpenNTF/darwino.org The code depends on some core Darwino classes (JSON, utilities…) but these are part of Darwino community edition 24#engageug
  25. 25. Schemaless GraphQL Queries GraphQL uses static schemas to validate the queries and make them discoverable by tools (code completion…) This forces the queries to be fully defined on the producer side All the fields have to be predefined All the relations between data sets have to be predefined as well What about semi structured data, like Domino documents? -> Would benefit from more flexibility To seamlessly access the data in an unstructured document To make prototyping easier and faster To traverse relations that are not known upfront 25#engageug
  26. 26. Dynamic JSON Data Type A JSON data type is a GraphQL type that exposes its content as a virtual JSON Object Its dynamic content is accessed using pseudo fields extract the value using JSON Path 26#engageug
  27. 27. A Simple Domino Example Reading items from an existing Domino document DominoDocument is a pseudo field loading a document based on parameters, and returning a JSON data type string is a pseudo field extracting a string value from a JSON data type using a JSON path 27#engageug doc: DominoDocument(database:"DarwinoReports.nsf", unid:"DD2028D6B53ADCCB852581080009C40E") { _unid, code: string(path:"PRODUCTCODE"), name: string(path:"PRODUCTNAME"), } https://playground.darwino.com/playground.nsf/GraphqlSnippets.xsp#snippet=Notes_Domino_Read_Document
  28. 28. Dynamic JSON Types Dynamic JSON types are pseudo fields that can be added any object By convention, these fields start with a capital letter, like a class in Java: DominoDocument, DominoView… They are used with an alias to name the result field Dynamic types are contributed by extension points,then added to every type in the final GraphQL schema. 28#engageug view: DominoView(name: “myview”){ … doc: DominoDocument(unid: ‘xxx’) { … } }
  29. 29. Dynamic JSON Fields Dynamic fields are also peudo fields, extracting a value using a JSON path and coercing the result to the desired type: New dynamic fields can be added by the developers 29#engageug val: string(path:“a.b.c") val: number(path:“a.b.c") val: int:“a.b.c") val: long(path:“a.b.c") val: boolean(path:“a.b.c") val: value(path:“a.b.c") val: eval(formula:“@Trim(@UserName)")
  30. 30. JSON Path Introduction A JSON Path is to JSON what an XPath is to XML The syntax is closed to JavaScript, starting with a ‘$’ $.firstName $.spouse.firstName $.spouse[‘firstName’] $.addresses[1].street $ {whole document} There are more complex operators http://goessner.net/articles/JsonPath/ Darwino core provides a high performance, advanced JSON Path engine 30#engageug { firstName: ‘Barak’, spouse: { firstName: ‘Michele’, … } addresses: [ { street: ‘Main St’, …}, { street: ‘Bob Sq’, …}, ], … }
  31. 31. Static Fields A JSON dynamic type can mix and match static fields with dynamic ones By convention, system fields start with a ‘_’ (_unid, …) Functional static fields can be added 31#engageug DominoDocument(database:"DarwinoReports.nsf", unid:"DD2028D6B53ADCCB852581080009C40E") { _unid, _noteId, _created, _lastAccessed, user { cn, dn } name: string(path:"PRODUCTNAME"), }
  32. 32. Passing Parameters to JSON Types In the previous Domino example, the unid parameter is hard coded which is not that useful… unid can be set from a GraphQL variable, but this is also global to the request – cannot be used for relations Darwino implementation uses a special syntax to calculate parameters Delegates the evaluation of ‘docid’ to the parent object Drawback: all parameters have to be declared as strings in GraphQL 32#engageug doc: DominoDocument(unid:$VAR) doc: DominoDocument(unid:”${docid}”)
  33. 33. Parameters Example 33#engageug doc: CursorDocument(database:"playground", store:"owners") { dn: string(path:"dn"), firstName: string(path:"firstName"), lastName: string(path:"lastName"), pinballs: objectArray(path:"pinballs[*]") { pinball: Document(unid:"${ipdb}",database:"playground", store:"pinball") { name: string(path:"name"), manufacturer: string(path:"manufacturer"), released: number(path:"released"), players: long(path:"players"), flippers: int(path:"flippers") } } } https://playground.darwino.com/playground.nsf/GraphqlSnippets.xsp#snippet=Json_St ore_Document_Document_join_on_Unid
  34. 34. Mixing Content Mixing JSON documents with Users coming from LDAP 34#engageug docs: CursorDocuments(database:"playground", store:"owners“) { dn: string(path:"dn"), firstName: string(path:"firstName"), user:User(dn:"${dn}") { dn, cn, email } https://playground.darwino.com/playground.nsf/GraphqlSnippets.xsp#snippet=Mixed _Document_join_on_User_Directory___Unid
  35. 35. Java Client Builder • A GraphQL query is a text file that is always painful to build safely • Escaping the text pieces, quotes… • Making sure that all the braces { } are balanced • Format it to be either compacted or developer friendly • Darwino provides an easy to use builder to help the creation of queries in Java • Highly readable by developer • Supports code completion in a Java IDE • Based on the Java Builder pattern • Fully extensible to handle known objects 35#engageug
  36. 36. A Simple GraphQL Query 36#engageug query MyQuery { field1 name: field2 field3(p=‘3’) { subfield } } String q = new GQuery("MyQuery") .field("field1") .field(“name", "field2") .field(new GField(field3) { .attribute(“p”,”3”) .field(“subfield") }) .build();
  37. 37. Example from the Playground Putting it altogether… 37#engageug String q = new GQuery("example") .field(new GField("Document") .attribute("unid", "1000") .attribute("database", "playground") .attribute("store", "pinball") .field("_id") .field("_unid") .field("_cdate") .field("_muser") .stringField("name","name") .stringField("manufacturer","manufacturer") .numberField("released","released") .longField("players","players") .intField("flippers","flippers") ).build(); https://playground.darwino.com/playground.nsf/JavaSnippets.xsp#snippet=GraphQL_Run_Inline_Client_Query
  38. 38. Watson Work Services Java SDK Java SDK for Watson Work Service • On OpenCode4Workspace (run by OpenNTF) • Download the project • Consume from Maven <dependency> <groupId>org.opencode4workspace.watson-work-services</groupId> <artifactId>wws-api</artifactId> <version>0.6.0</version> </dependency> • View source code on Stash (includes Junit tests) • Explore implementation in Watson Workspace for Eclipse / Notes Latest documentation on OpenNTF Wiki, Javadoc available 38#engageug
  39. 39. Watson Work Services Java SDK Client authentication as application Client authentication as user Build queries with Java objects, methods and enums • No need to construct queries as complex Strings Methods to output built query as String and response as String Conversion of response to Java objects Methods to parse error responses Standard REST endpoints also supported 39#engageug
  40. 40. WWS Java SDK Samples 40#engageug
  41. 41. WWS Java SDK Samples 41#engageug
  42. 42. WWS Java SDK Variables not current supported • Use Java method to construct query based on variable Fragments not currently supported • Use Java method / object to specify standard fields Directives not currently supported • Use Java method to construct query based on variable Aliases not currently supported • Track the JIRA issue 42#engageug
  43. 43. Resources GraphQL website, http://graphql.org GraphQL community resources, http://graphql.org/community/ GraphQL Visualization Tool, http://nathanrandal.com/graphql- visualizer/ WWS developer documentation, https://workspace.ibm.com/developer/docs WWS GraphiQL IDE, https://workspace.ibm.com/graphql WWS API Java SDK, https://openntf.org/main.nsf/project.xsp?r=project/Watson%20 Work%20Services%20Java%20SDK 43#engageug
  44. 44. Thank You 44#engageug Paul Withers Intec Systems Ltd & OpenNTF pwithers@intec.co.uk @paulswithers https://www.intec.co.uk/blog https://paulswithers.github.io Philippe Riand Darwino Inc. phil@darwino.com @philriand http://blog.riand.com/ https://www.darwino.com/

×