Slide 1

Slide 1 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. 0 to 100 with GraphQL: Rapid Development Techniques for APIs { "name": "Sébastien Stormacq", "role": ”Technical Evangelist", "company": "Amazon Web Services”, "twitter": ”@sebsto”, ”github": ”sebsto” } B A R 4 U T R E C H T 1 9 . 0 6 . 2 0 1 9

Slide 2

Slide 2 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. This talk is for developers

Slide 3

Slide 3 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. This talk is for developers < frontend | backend >

Slide 4

Slide 4 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. How to you prototype API ?

Slide 5

Slide 5 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Congratulations ! You’ve just been hired.

Slide 6

Slide 6 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved.

Slide 7

Slide 7 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Today’s mobile experience is lacking Mobile website, no native apps Slow to book, low conversion rates Backend built for high-speed desktops !

Slide 8

Slide 8 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Your job is to define tomorrow’s experience Digital agencies hired for design First prototype in 4 weeks Must use real data, no mockup "

Slide 9

Slide 9 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Our Goal Enable backend services for prototype Allow design to evolve Keeping up with day-to-day job #

Slide 10

Slide 10 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. { "_id": 3, "name": "ElastiLodge South Zanetown", "image": "https://placehold.it/300x300.png", "description": "Sint nostrum vel quibusdam quia reprehenderit cum exercitationem quia ea.", "location": "South Zanetown", "manager": { "name": "Florentino Jacobi", "email": "[email protected]" }, "timeZone": "US/Central", "phoneNumber": "802-918-3262", "category": 5, Legacy REST API "address": { "street": "410 Simonis Forest", "zip": "07545-2308", "city": "South Zanetown", "country": "Virgin Islands, British" }, "deskHours": "24 hours", "amenities": [ ... ], "restaurants": [ ... ] }

Slide 11

Slide 11 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. What are the challenges of REST API

Slide 12

Slide 12 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. /posts /comments /authors REST API Chatty & Over fetching { "posts" : [ { "id" : 1, "content" : "the quick brown fox jumps over the…", "author" : "/authors/123", "created" : 1550486509, "comments" : "/posts/1/comments", ... }, { "id" : 2, "content" : "the quick brown fox jumps over…", "author" : "/authors/123" "created" : 1550486509, "comments" : "/posts/2/comments", ... } ] }

Slide 13

Slide 13 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Introducing GraphQL

Slide 14

Slide 14 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. https://graphql.org

Slide 15

Slide 15 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Why GraphQL ? posts comments authors GraphQL API

Slide 16

Slide 16 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. How does GraphQL work? type Query { getTodos: [Todo] } type Todo { id: ID! name: String description: String priority: Int duedate: String } Model data with application schema query { getTodos { id name priority } } Client requests what it needs { "id": "1", "name": "Get Milk", "priority": "1" }, { "id": "2", "name": "Go to gym", "priority": "5" },… Only that data is returned

Slide 17

Slide 17 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. GraphQL Operations Queries Read data Mutations Write data Subscriptions Listen for data query { search(q: “harry potter”) { title } } mutation { create(title: “new book”) { id } } subscription { onCreate { id title } }

Slide 18

Slide 18 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Is REST dead then? When data drives UI Structured data Query-driven Client-driven development Use GraphQL When you leverage HTTP Caching, Content types Hypermedia (HATEOAS) For resources (eg Amazon S3) Use REST Pick the appropriate protocol for your use case

Slide 19

Slide 19 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. How to deploy GraphQL API ?

Slide 20

Slide 20 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. AWS App Sync Managed serverless GraphQL service Connect to data sources in your account Add data sync, real-time, and offline capabilities for any data source or API GraphQL facade for any AWS service Conflict detection and resolution in the cloud Enterprise security features: IAM, Amazon Cognito, OIDC, API keys

Slide 21

Slide 21 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. AppSync Data Sources

Slide 22

Slide 22 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. AppSync Resolvers

Slide 23

Slide 23 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Hello AWS AppSync KEEP CALM and WATCH the DEMO

Slide 24

Slide 24 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Prototype : Phase #1 Hotel Detail

Slide 25

Slide 25 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Hotel Detail: Design What data is required? Can we use existing data sources? How can we enable via AppSync? Challenges? Missing data?

Slide 26

Slide 26 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mapping to Legacy API { "_id": 3, "image": "https://placehold.it/300x300.png", "name": "EL Resort & Spa", "description": "...", "location": "Fiji", "manager": { "name": "Florentino Jacobi", "email": "[email protected]" }, "timeZone": "US/Central", "address": { "street": "123 Main St", ”postalcode": "07545", "city": "Momi Bay", "country": "Fiji" }, "phoneNumber": "1-888-123-4567", "category": 5, "deskHours": "24 hours", "amenities": [ ... ], "restaurants": [ ... ] }

Slide 27

Slide 27 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mapping to Legacy API { "_id": 3, "image": "https://placehold.it/300x300.png", "name": "EL Resort & Spa", "description": "...", "location": "Fiji", "manager": { "name": "Florentino Jacobi", "email": "[email protected]" }, "timeZone": "US/Central", "address": { "street": "123 Main St", ”postalcode": "07545", "city": "Momi Bay", "country": "Fiji" }, "phoneNumber": "1-888-123-4567", "category": 5, "deskHours": "24 hours", "amenities": [ ... ], "restaurants": [ ... ] }

Slide 28

Slide 28 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Hotel Detail: GraphQL Schema type Hotel { hotelId: ID! name: String! image: String location: String! phoneNumber: AWSPhone! address: Address! ... } type Query { listHotels(offset: String, limit: Int) getHotel(hotelId: ID!) }

Slide 29

Slide 29 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Hotel Detail: Resolvers ## Resolver: Request Mapping ## { "version": "2018-05-29", "method": "GET", "resourcePath": "/hotels/${ctx.args.hotelId}", "params": { "headers": { "Content-Type": "application/json" } }, } ## Resolver: Response Mapping ## #if($ctx.result.statusCode == 200) ## If response is 200, return the body. ## Could also filter result... $ctx.result.body #else ## If not 200, append response to error $utils.appendError($ctx.result.body) #end

Slide 30

Slide 30 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Hotel Detail: Result query { getHotel(hotelId: 3) { name location image phoneNumber address { street city } amenities } } { "name": "ElastiLodge North Rodgerstad", "location": "North Rodgerstad", "image": "/300x300.png", "phoneNumber": "(214) 210-4674", "address": { "street": "123 Main St", "city": "North Rodgerstad" }, "amenities": [ ... ] }

Slide 31

Slide 31 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mobile Code – Initialize App Sync Client do { // create app sync configuration (cache, service config etc) let config = … // client initialization let appSyncClient = try AWSAppSyncClient(appSyncConfig: config) } catch { fatalError("Error initializing appsync client. \(error)") }

Slide 32

Slide 32 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mobile Code – Run a Query // call a GraphQL Query appSyncClient?.fetch(query: GetHotelQuery(hotelId: hotelId), cachePolicy: .fetchIgnoringCacheData) {(result, error) in guard let r = result, error == nil else { print(error?.localizedDescription ?? "") return } // use the data in the GUI self.hotelDetails = r.data?.getHotel … }

Slide 33

Slide 33 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mobile App – Phase 1 KEEP CALM and WATCH the DEMO

Slide 34

Slide 34 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations

Slide 35

Slide 35 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations: Design What data is required? Can we use existing data sources? How can we enable via AppSync? Challenges?

Slide 36

Slide 36 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations: GraphQL Schema type Reservation { confirmationNumber: ID! hotel: Hotel! guest: User! startDate: AWSDate! endDate: AWSDate! rate: Int! } type Query { ... reservations(guestId : ID!):[Reservation] } type Mutation { createReservation(input:ReservationInput) deleteReservation(confNum: ID!) }

Slide 37

Slide 37 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations: Query Resolver - Input #set( $todayString = $util.time.nowISO8601().substring(0, 10) ) { "version": "2017-02-28", "operation": "Query", "query": { "expression": "guestId = :gId AND startDate > :startDate", "expressionValues": { ":gId": $util.dynamodb.toDynamoDBJson($ctx.identity.sub), ":startDate": $util.dynamodb.toDynamoDBJson($todayString) } } } Note: assumes user is logged in via AWS Cognito User Pool. Details are outside our scope.

Slide 38

Slide 38 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations: Query Resolver - Output $util.toJson($ctx.result.items) Note: assumes user is logged in via AWS Cognito User Pool. Details are outside our scope.

Slide 39

Slide 39 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservations: Result query { guestReservations { confirmationNumber hotel { hotelId name image phoneNumber } startDate endDate } }

Slide 40

Slide 40 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Extending Reservation Workflow

Slide 41

Slide 41 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Subscription Query subscription ReservationSubscription { createReservationEvent(guestId:1) { confirmationNumber } }

Slide 42

Slide 42 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Mobile Code – Subscribe to changes let sub = CreateReservationEventSubscription(guestId: userId) newReservationSubscription = try appSyncClient?.subscribe(subscription: sub, resultHandler: { (result, transaction, error) in // check for error // store a reference to the new booking into our cache transaction?.update(query: GuestReservationsQuery(guestId: userId)) { (data: inout GuestReservationsQuery.Data) in data.guestReservations?.append(bookingToAdd) // consume the data in the UI self.bookingDetails?.append(bookingToAdd) } }

Slide 43

Slide 43 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Reservation Subscriptions KEEP CALM and WATCH the DEMO

Slide 44

Slide 44 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Adaptive Rates

Slide 45

Slide 45 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Adaptive Rates: Design R&D is building an adaptive rate capability Delivered via Amazon SageMaker API How do we add today’s rate to our existing API?

Slide 46

Slide 46 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Adaptive Rates: Evolving our GraphQL API GraphQL supports multiple data sources per query: 1. Add new field 2. Configure new Data Source and Resolvers

Slide 47

Slide 47 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Adaptive Rates: GraphQL Types and Resolvers type Hotel { hotelId: ID! name: String! location: String! ... rate: Rate } type Rate { hotelId: ID! rate: Int! currency: String! date: AWSDate! } ## rate Field Resolver: Request Mapping ## { "version": "2018-05-29", "method": "GET", "resourcePath": "/rd/rates/${ctx.source.hotelId}", "params": { "headers": { "Content-Type": "application/json" } } }

Slide 48

Slide 48 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Adaptive Rates: Result query { getHotel(hotelId: 3) { name location image phoneNumber address { street city } amenities rate { currency rate } } } { "name": "ElastiLodge North Rodgerstad", "location": "North Rodgerstad", "image": "https://placehold.it/300x300.png", "phoneNumber": "(214) 210-4674", "address": { "street": "", "city": "" }, "amenities": [ ... ], "rate": { "currency": "USD", "rate": 312 } }

Slide 49

Slide 49 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Field-level resolution KEEP CALM and WATCH the DEMO

Slide 50

Slide 50 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. What did we just did ?

Slide 51

Slide 51 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. What did we accomplish today? Built a rich, flexible, mobile-ready API Incorporated legacy, new, and prototype features in a single endpoint Evolved API as requirements changed No coding required! Well, there were a few Velocity Templates AWS Console includes starter / boilerplate templates

Slide 52

Slide 52 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. AWS Amplify CLI Toolchain for developers Enables you to prototype and build quickly Built-in GraphQL Transformer Converts schema to CloudFormation templates and builds cloud resources $ amplify api add # create GraphQL schema # for example: type Hotel @model @searchable { name: String! location: String! ... } https://github.com/aws-amplify/amplify-cli

Slide 53

Slide 53 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Backend Engineer: Hmm. So you’re saying this “GraphQL” will allow any web or native engineer to arbitrarily query basically any field in any backend service, recursively, however they want, without any backend engineers involved? Frontend Engineer: Yeah, right? It’s amazing! […silence…] Backend Engineer: Guards, seize this person.

Slide 54

Slide 54 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Real world pitfalls

Slide 55

Slide 55 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Advanced Authorization : nested queries

Slide 56

Slide 56 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. type AuthCheckData { id: ID! data: Data } type Data { id: ID! title: String content: String } type Query { getData(id:ID!): AuthCheckData }

Slide 57

Slide 57 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved.

Slide 58

Slide 58 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Learn More : https://hackernoon.com/graphql-authorization-with-multiple-data-sources-using-aws-appsync-dfae2e350bf2

Slide 59

Slide 59 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Code presented today https://github.com/sebsto/reinvent2018-mob320

Slide 60

Slide 60 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Great GraphQL Podcasts

Slide 61

Slide 61 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Thank you! © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. { "name": "Sébastien Stormacq", "role": ”Technical Evangelist", "company": "Amazon Web Services”, "twitter": ”@sebsto”, ”github": ”sebsto” }

Slide 62

Slide 62 text

© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved. Please complete the session survey in the mobile app. © 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved.