SlideShare a Scribd company logo
1 of 53
Download to read offline
LESSONS LEARNED FROM IMPLEMENTING A GRAPHQL API
Dirk-Jan @excite-engineer
Dirk is a Software Engineer with a
focus on Javascript who gets (way
too) excited about writing stable and
well tested code. GraphQL fan.
Florentijn @Mr_Blue_Sql
GraphQL enthusiast. Focusing on
Javascript and realizing highly
available, easy to maintain solutions
on AWS. I like giving high ves.
HI THERE
hi-there.community
Agenda
What is GraphQL?
Lessons Learned from
implementing a GraphQL API
What is GraphQL?
A query language for your API
Properties
Client controls data, not the server
Multiple resources in a single
request
Documentation is awesome
Type system
Developer tools: GraphiQL
GraphQL Demo
LESSON 1
Separation of concerns
Query Joke
{
joke(id: "1") {
id
text
funnyLevel
}
}
Implement the query
const query = {
joke: {
type: GraphQLJoke,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) {
return db.joke.findById(args.id);
}
}
}
Authorization: Joke can only be retrieved
by creator
const query = {
joke: {
type: GraphQLJoke,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: async (root, args, context) {
const data = await db.joke.findById(args.id);
if (data == null) return null;
/* Authorization */
const canSee = data.creator === context.viewer.id;
return canSee ? data : null;
}
}
}
Implement the Joke object type.
const GraphQLJoke = new GraphQLObjectType({
name: 'Joke',
fields: {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (data) => data.id
},
text: {
type: new GraphQLNonNull(GraphQLString),
resolve: (data) => data.text
},
funnyLevel: {
type: new GraphQLNonNull(GraphQLInt),
resolve: (data) => data.funnyLevel
}
}
});
Result
{
joke(id: "1") {
id
text
funnyLevel
}
}
{
"joke": {
"id": "1",
"text": "What is the key difference between snowmen and snowwomen? Snowballs.",
"funnyLevel": 0
}
}
Update joke mutation
mutation {
updateJoke(jokeId: "1", funnyLevel: 10) {
id
text
funnyLevel
}
}
Implementation in GraphQL
const mutation = {
type: new GraphQLNonNull(GraphQLJoke),
description: "Update a joke.",
args: {
jokeId: { type: new GraphQLNonNull(GraphQLID) },
funnyLevel: { type: new GraphQLNonNull(GraphQLInt) }
},
resolve: (root, args, context) => {
//...
}
}
Duplicate authorization logic
resolve: async (root, args, context) => {
/* validation */
if (args.funnyLevel < 0 || args.funnyLevel > 5)
throw new Error('Invalid funny level.');
const data = await db.joke.findById(args.jokeId);
if (data == null) throw new Error('No joke exists for the id');
/* authorization */
if (data.creator !== context.viewer.id) throw new Error('No joke exists for the id')
/* Perform update */
data.funnyLevel = funnyLevel;
async data.save();
return data;
}
Result
mutation {
updateJoke(jokeId: "1", funnyLevel: 10) {
id
text
funnyLevel
}
}
{
"errors": [
{
"message": "Invalid funny level",
}
]
}
Building out the schema
Retrieve a list of jokes
Delete a joke
Create a joke
...
Authorization/Database logic all over the
place!
Direct effects
Logic spread around independent
GraphQL resolvers: Hard to keep in sync.
Testing dif cult.
Hard to maintain.
Long term issues: In exibility
Hard to switch from GraphQL to
other API protocol.
Hard to switch to other DB type.
The solution! Separation
Business Logic
Single source of truth for enforcing
business rules.
Determines how data is retrieved,
created and updated from DB.
Performs authorization for data
Performs validation
Connecting GraphQL to the business
logic:
Resolver functions maps directly to the
business logic.
Example 1: Query Joke
{
joke(id: "1") {
id
text
funnyLevel
}
}
Before the split
const query = {
joke: {
type: GraphQLJoke,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: async (root, args, context) {
const data = await db.joke.findById(args.id);
if (data == null) return null;
/* Authorization */
const canSee = data.creator === context.viewer.id;
return canSee ? data : null;
}
}
}
After the split
import Joke from "../logic";
const query = {
joke: {
type: GraphQLJoke,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args, context) => Joke.gen(context.viewer, args.id)
}
}
Business logic Layer
const areYouOwner = (viewer: User, data) => {
return viewer.id === data.creator;
}
class Joke {
static async gen(viewer: User, id: string): Promise<?Joke> {
const data = await db.joke.findById(id);
if (data == null) return null;
const canSee = areYouOwner(viewer, data);
return canSee ? new Joke(data) : null;
}
constructor(data: Object) {
this.id = String(data.id);
this.text = data.text;
this.funnyLevel = data.funnyLevel;
}
}
Example 2: Mutation to update a joke
mutation {
updateJoke(jokeId: "1", funnyLevel: 10) {
id
text
funnyLevel
}
}
GraphQL
const mutation = {
type: new GraphQLNonNull(GraphQLJoke),
description: "Update a joke.",
args: {
jokeId: { type: new GraphQLNonNull(GraphQLID) },
funnyLevel: { type: new GraphQLNonNull(GraphQLInt) }
},
resolve: (root, args, context) => {
//...
}
}
Single source of truth for authorization
import Joke from "../logic";
resolve: (root, args, context) => {
/* Authorization */
const joke = Joke.gen(context.viewer, args.jokeId);
if (!joke) throw new Error('No joke found for the id');
/* Performs validation and updates DB */
joke.setFunnyLevel(args.funnyLevel);
return joke;
}
- graphql.org
Bene ts
Single source of truth for enforcing
business rules.
Testability
Maintainable
LESSON 2
Relay Compliant Schema
What is it?
A GraphQL schema speci cation that
makes strong assumptions about
refetching, pagination, and realizing
mutation predictability.
Client Side Caching
Joke Query
//GraphQL query:
query {
viewer {
id
jokes {
id
}
}
}
//Result:
{
"viewer": {
"id": "1",
"jokes": [{
"id": "1"
}]
}
}
Solution
Create globally unique opaque ids
Joke Query Unique Ids
//GraphQL query:
query {
viewer {
id
jokes {
id
}
}
}
//Result:
{
"viewer": {
"id": "Sh3Ee!p=",
"jokes": [{
"id": "m0=nK3Y!"
}]
}
}
The Result
Caching becomes simple
Database assumptions opaque to
client
... and every object can easily be
refetched
Refetching
Retrieve resource using single query
query {
node(id: "E4sT3r!39g=") {
id
... on Joke {
title
funnyness
}
}
}
Pagination
List Example
"data" {
"viewer" {
"jokes": [
{
"id": "1",
"text": "How do you make a tissue"
},
...
{
"id": "500",
"text": "Pfooo, only half way"
},
...
{
"id": "1000",
Why Pagination?
More ne-grained control
Prevents app from being slow
Improves back-end performance
Pagination done right using connection
approach
query {
viewer {
jokes(first: 10 /*The offset*/, after: "TUr71e=!" /*Cursor*/) {
edges {
cursor //Cursor
node {
text
funnyLevel
}
}
pageInfo { //pageInfo contains info about whether there exist more edges
hasNextPage
}
}
}
}
Opportunity to change to Relay if you
wish
Advantages Relay Compliant Schema
Enforce globally unique id that is
opaque
Any resource that belongs to you
can be retrieved using a single query
Pagination for lists is built in
Opportunity to change to Relay if
you wish
To Sum Up
Lesson 1: API, Business Logic,
Persistence Layer
Lesson 2: Relay compliant schema
More Lessons
Authentication
Caching & Batching
Error Handling
Reach us on twitter!
@excite-engineer
@Mr_Blue_Sql
Thanks!

More Related Content

What's hot

Fun with QML
Fun with QMLFun with QML
Fun with QMLICS
 
Presente e Futuro: Java EE.next()
Presente e Futuro: Java EE.next()Presente e Futuro: Java EE.next()
Presente e Futuro: Java EE.next()Bruno Borges
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Eheinovex GmbH
 
Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automationMario Fusco
 
Jug Guice Presentation
Jug Guice PresentationJug Guice Presentation
Jug Guice PresentationDmitry Buzdin
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularLoiane Groner
 
Dagger 2. Right way to do Dependency Injection
Dagger 2. Right way to do Dependency InjectionDagger 2. Right way to do Dependency Injection
Dagger 2. Right way to do Dependency InjectionStfalcon Meetups
 
Dagger 2. The Right Way to Dependency Injections
Dagger 2. The Right Way to Dependency InjectionsDagger 2. The Right Way to Dependency Injections
Dagger 2. The Right Way to Dependency InjectionsGlobalLogic Ukraine
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & WebpackCodifly
 
CodeWay 2019 - Gandalf: Bad code shall not pass
CodeWay 2019 - Gandalf: Bad code shall not passCodeWay 2019 - Gandalf: Bad code shall not pass
CodeWay 2019 - Gandalf: Bad code shall not passIlya Ghirici
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 
Android DevConference - Android Clean Architecture
Android DevConference - Android Clean ArchitectureAndroid DevConference - Android Clean Architecture
Android DevConference - Android Clean ArchitectureiMasters
 
A friend in need - A JS indeed
A friend in need - A JS indeedA friend in need - A JS indeed
A friend in need - A JS indeedYonatan Levin
 
Software engineering ⊇ Software testing
Software engineering ⊇ Software testingSoftware engineering ⊇ Software testing
Software engineering ⊇ Software testingPavel Tcholakov
 
Droid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroidConTLV
 
Serverless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applicationsServerless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applicationsLoiane Groner
 
React table tutorial use filter (part 2)
React table tutorial use filter (part 2)React table tutorial use filter (part 2)
React table tutorial use filter (part 2)Katy Slemon
 

What's hot (20)

Google Guice
Google GuiceGoogle Guice
Google Guice
 
Fun with QML
Fun with QMLFun with QML
Fun with QML
 
Presente e Futuro: Java EE.next()
Presente e Futuro: Java EE.next()Presente e Futuro: Java EE.next()
Presente e Futuro: Java EE.next()
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Ehe
 
Kogito: cloud native business automation
Kogito: cloud native business automationKogito: cloud native business automation
Kogito: cloud native business automation
 
Jug Guice Presentation
Jug Guice PresentationJug Guice Presentation
Jug Guice Presentation
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + Angular
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
Dagger 2. Right way to do Dependency Injection
Dagger 2. Right way to do Dependency InjectionDagger 2. Right way to do Dependency Injection
Dagger 2. Right way to do Dependency Injection
 
Dagger 2. The Right Way to Dependency Injections
Dagger 2. The Right Way to Dependency InjectionsDagger 2. The Right Way to Dependency Injections
Dagger 2. The Right Way to Dependency Injections
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
 
CodeWay 2019 - Gandalf: Bad code shall not pass
CodeWay 2019 - Gandalf: Bad code shall not passCodeWay 2019 - Gandalf: Bad code shall not pass
CodeWay 2019 - Gandalf: Bad code shall not pass
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 
Android DevConference - Android Clean Architecture
Android DevConference - Android Clean ArchitectureAndroid DevConference - Android Clean Architecture
Android DevConference - Android Clean Architecture
 
Angular mix chrisnoring
Angular mix chrisnoringAngular mix chrisnoring
Angular mix chrisnoring
 
A friend in need - A JS indeed
A friend in need - A JS indeedA friend in need - A JS indeed
A friend in need - A JS indeed
 
Software engineering ⊇ Software testing
Software engineering ⊇ Software testingSoftware engineering ⊇ Software testing
Software engineering ⊇ Software testing
 
Droid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, KikDroid on Chain - Berry Ventura Lev, Kik
Droid on Chain - Berry Ventura Lev, Kik
 
Serverless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applicationsServerless Angular, Material, Firebase and Google Cloud applications
Serverless Angular, Material, Firebase and Google Cloud applications
 
React table tutorial use filter (part 2)
React table tutorial use filter (part 2)React table tutorial use filter (part 2)
React table tutorial use filter (part 2)
 

Viewers also liked

My learnings on web performance optimization while building a Progressive Web...
My learnings on web performance optimization while building a Progressive Web...My learnings on web performance optimization while building a Progressive Web...
My learnings on web performance optimization while building a Progressive Web...Narendra Shetty
 
Mariana Bessa Portfólio Social Media 2017
Mariana Bessa Portfólio Social Media 2017Mariana Bessa Portfólio Social Media 2017
Mariana Bessa Portfólio Social Media 2017Mariana Bessa
 
BusRide GreenRoad Fleet Management Webinar
BusRide GreenRoad Fleet Management WebinarBusRide GreenRoad Fleet Management Webinar
BusRide GreenRoad Fleet Management WebinarMiles Driven
 
Defendamos la unión, la dignidad y la soberanía de nuestra américa
Defendamos la unión, la dignidad y la soberanía de nuestra américaDefendamos la unión, la dignidad y la soberanía de nuestra américa
Defendamos la unión, la dignidad y la soberanía de nuestra américaNorelys Morales Aguilera
 
discharge planning
discharge planningdischarge planning
discharge planningTas Hind MSc
 
FICM - Forensic Intensive Case Management
FICM - Forensic Intensive Case ManagementFICM - Forensic Intensive Case Management
FICM - Forensic Intensive Case ManagementGreg McCutcheon
 
understanding-the-discharge-process-sept-2015-2
understanding-the-discharge-process-sept-2015-2understanding-the-discharge-process-sept-2015-2
understanding-the-discharge-process-sept-2015-2Alex Howat
 
Transition of Patient from Hospital to Home/Next Level of Care
Transition of Patient from Hospital to Home/Next Level of CareTransition of Patient from Hospital to Home/Next Level of Care
Transition of Patient from Hospital to Home/Next Level of CareKaiser Permanente
 
Enhancing Mental Health Care Transitions: A Recovery-Based Model
Enhancing Mental Health Care Transitions: A Recovery-Based ModelEnhancing Mental Health Care Transitions: A Recovery-Based Model
Enhancing Mental Health Care Transitions: A Recovery-Based ModelAllina Health
 
Diapositiva esther uapa
Diapositiva esther uapaDiapositiva esther uapa
Diapositiva esther uapadenia2194
 
Hospital Discharge planning for Spinal cord injured patients.
Hospital Discharge planning for Spinal cord injured patients.Hospital Discharge planning for Spinal cord injured patients.
Hospital Discharge planning for Spinal cord injured patients.Vishnu P.V
 
Discharges
Discharges  Discharges
Discharges wcmc
 
Discharge planning 2014
Discharge planning 2014Discharge planning 2014
Discharge planning 2014kmwall
 

Viewers also liked (14)

My learnings on web performance optimization while building a Progressive Web...
My learnings on web performance optimization while building a Progressive Web...My learnings on web performance optimization while building a Progressive Web...
My learnings on web performance optimization while building a Progressive Web...
 
Mariana Bessa Portfólio Social Media 2017
Mariana Bessa Portfólio Social Media 2017Mariana Bessa Portfólio Social Media 2017
Mariana Bessa Portfólio Social Media 2017
 
BusRide GreenRoad Fleet Management Webinar
BusRide GreenRoad Fleet Management WebinarBusRide GreenRoad Fleet Management Webinar
BusRide GreenRoad Fleet Management Webinar
 
Defendamos la unión, la dignidad y la soberanía de nuestra américa
Defendamos la unión, la dignidad y la soberanía de nuestra américaDefendamos la unión, la dignidad y la soberanía de nuestra américa
Defendamos la unión, la dignidad y la soberanía de nuestra américa
 
discharge planning
discharge planningdischarge planning
discharge planning
 
FICM - Forensic Intensive Case Management
FICM - Forensic Intensive Case ManagementFICM - Forensic Intensive Case Management
FICM - Forensic Intensive Case Management
 
understanding-the-discharge-process-sept-2015-2
understanding-the-discharge-process-sept-2015-2understanding-the-discharge-process-sept-2015-2
understanding-the-discharge-process-sept-2015-2
 
Transition of Patient from Hospital to Home/Next Level of Care
Transition of Patient from Hospital to Home/Next Level of CareTransition of Patient from Hospital to Home/Next Level of Care
Transition of Patient from Hospital to Home/Next Level of Care
 
Discharge plan
Discharge planDischarge plan
Discharge plan
 
Enhancing Mental Health Care Transitions: A Recovery-Based Model
Enhancing Mental Health Care Transitions: A Recovery-Based ModelEnhancing Mental Health Care Transitions: A Recovery-Based Model
Enhancing Mental Health Care Transitions: A Recovery-Based Model
 
Diapositiva esther uapa
Diapositiva esther uapaDiapositiva esther uapa
Diapositiva esther uapa
 
Hospital Discharge planning for Spinal cord injured patients.
Hospital Discharge planning for Spinal cord injured patients.Hospital Discharge planning for Spinal cord injured patients.
Hospital Discharge planning for Spinal cord injured patients.
 
Discharges
Discharges  Discharges
Discharges
 
Discharge planning 2014
Discharge planning 2014Discharge planning 2014
Discharge planning 2014
 

Similar to Lessons Learned Implementing a GraphQL API

GraphQL_devoxx_2023.pptx
GraphQL_devoxx_2023.pptxGraphQL_devoxx_2023.pptx
GraphQL_devoxx_2023.pptxSoham Dasgupta
 
GraphQL-ify your API - JFall 2022
GraphQL-ify your API - JFall 2022GraphQL-ify your API - JFall 2022
GraphQL-ify your API - JFall 2022Soham Dasgupta
 
GraphQL the holy contract between client and server
GraphQL the holy contract between client and serverGraphQL the holy contract between client and server
GraphQL the holy contract between client and serverPavel Chertorogov
 
Everything as a Code / Александр Тарасов (Одноклассники)
Everything as a Code / Александр Тарасов (Одноклассники)Everything as a Code / Александр Тарасов (Одноклассники)
Everything as a Code / Александр Тарасов (Одноклассники)Ontico
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
Tutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPTutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPAndrew Rota
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchNikolas Burk
 
Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Tugdual Grall
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedMarcinStachniuk
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Mike Nakhimovich
 
Professional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsProfessional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsMike Wilcox
 
Vaadin 7 Today and Tomorrow
Vaadin 7 Today and TomorrowVaadin 7 Today and Tomorrow
Vaadin 7 Today and TomorrowJoonas Lehtinen
 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!Sébastien Levert
 
Reusing your frontend JS on the server with V8/Rhino
Reusing your frontend JS on the server with V8/RhinoReusing your frontend JS on the server with V8/Rhino
Reusing your frontend JS on the server with V8/RhinoKenneth Kalmer
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
Apollo. The client we deserve
Apollo. The client we deserveApollo. The client we deserve
Apollo. The client we deserveYuri Nezdemkovski
 

Similar to Lessons Learned Implementing a GraphQL API (20)

GraphQL_devoxx_2023.pptx
GraphQL_devoxx_2023.pptxGraphQL_devoxx_2023.pptx
GraphQL_devoxx_2023.pptx
 
GraphQL-ify your API - JFall 2022
GraphQL-ify your API - JFall 2022GraphQL-ify your API - JFall 2022
GraphQL-ify your API - JFall 2022
 
GraphQL the holy contract between client and server
GraphQL the holy contract between client and serverGraphQL the holy contract between client and server
GraphQL the holy contract between client and server
 
Everything as a Code / Александр Тарасов (Одноклассники)
Everything as a Code / Александр Тарасов (Одноклассники)Everything as a Code / Александр Тарасов (Одноклассники)
Everything as a Code / Александр Тарасов (Одноклассники)
 
Everything as a code
Everything as a codeEverything as a code
Everything as a code
 
GraphQL-ify your APIs
GraphQL-ify your APIsGraphQL-ify your APIs
GraphQL-ify your APIs
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Enterprise Java Puzzlers
Enterprise Java PuzzlersEnterprise Java Puzzlers
Enterprise Java Puzzlers
 
Tutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPTutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHP
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from Scratch
 
Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Scripting Oracle Develop 2007
Scripting Oracle Develop 2007
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learned
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
 
Professional JavaScript: AntiPatterns
Professional JavaScript: AntiPatternsProfessional JavaScript: AntiPatterns
Professional JavaScript: AntiPatterns
 
Vaadin 7 Today and Tomorrow
Vaadin 7 Today and TomorrowVaadin 7 Today and Tomorrow
Vaadin 7 Today and Tomorrow
 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!
 
Reusing your frontend JS on the server with V8/Rhino
Reusing your frontend JS on the server with V8/RhinoReusing your frontend JS on the server with V8/Rhino
Reusing your frontend JS on the server with V8/Rhino
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Apollo. The client we deserve
Apollo. The client we deserveApollo. The client we deserve
Apollo. The client we deserve
 

Recently uploaded

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 

Recently uploaded (20)

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 

Lessons Learned Implementing a GraphQL API

  • 1. LESSONS LEARNED FROM IMPLEMENTING A GRAPHQL API
  • 2. Dirk-Jan @excite-engineer Dirk is a Software Engineer with a focus on Javascript who gets (way too) excited about writing stable and well tested code. GraphQL fan. Florentijn @Mr_Blue_Sql GraphQL enthusiast. Focusing on Javascript and realizing highly available, easy to maintain solutions on AWS. I like giving high ves.
  • 4. Agenda What is GraphQL? Lessons Learned from implementing a GraphQL API
  • 5. What is GraphQL? A query language for your API
  • 6. Properties Client controls data, not the server Multiple resources in a single request Documentation is awesome Type system Developer tools: GraphiQL
  • 9. Query Joke { joke(id: "1") { id text funnyLevel } }
  • 10. Implement the query const query = { joke: { type: GraphQLJoke, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: (root, args) { return db.joke.findById(args.id); } } }
  • 11. Authorization: Joke can only be retrieved by creator const query = { joke: { type: GraphQLJoke, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: async (root, args, context) { const data = await db.joke.findById(args.id); if (data == null) return null; /* Authorization */ const canSee = data.creator === context.viewer.id; return canSee ? data : null; } } }
  • 12. Implement the Joke object type. const GraphQLJoke = new GraphQLObjectType({ name: 'Joke', fields: { id: { type: new GraphQLNonNull(GraphQLID), resolve: (data) => data.id }, text: { type: new GraphQLNonNull(GraphQLString), resolve: (data) => data.text }, funnyLevel: { type: new GraphQLNonNull(GraphQLInt), resolve: (data) => data.funnyLevel } } });
  • 13. Result { joke(id: "1") { id text funnyLevel } } { "joke": { "id": "1", "text": "What is the key difference between snowmen and snowwomen? Snowballs.", "funnyLevel": 0 } }
  • 14. Update joke mutation mutation { updateJoke(jokeId: "1", funnyLevel: 10) { id text funnyLevel } }
  • 15. Implementation in GraphQL const mutation = { type: new GraphQLNonNull(GraphQLJoke), description: "Update a joke.", args: { jokeId: { type: new GraphQLNonNull(GraphQLID) }, funnyLevel: { type: new GraphQLNonNull(GraphQLInt) } }, resolve: (root, args, context) => { //... } }
  • 16. Duplicate authorization logic resolve: async (root, args, context) => { /* validation */ if (args.funnyLevel < 0 || args.funnyLevel > 5) throw new Error('Invalid funny level.'); const data = await db.joke.findById(args.jokeId); if (data == null) throw new Error('No joke exists for the id'); /* authorization */ if (data.creator !== context.viewer.id) throw new Error('No joke exists for the id') /* Perform update */ data.funnyLevel = funnyLevel; async data.save(); return data; }
  • 17. Result mutation { updateJoke(jokeId: "1", funnyLevel: 10) { id text funnyLevel } } { "errors": [ { "message": "Invalid funny level", } ] }
  • 18. Building out the schema Retrieve a list of jokes Delete a joke Create a joke ...
  • 20. Direct effects Logic spread around independent GraphQL resolvers: Hard to keep in sync. Testing dif cult. Hard to maintain.
  • 21. Long term issues: In exibility Hard to switch from GraphQL to other API protocol. Hard to switch to other DB type.
  • 23. Business Logic Single source of truth for enforcing business rules. Determines how data is retrieved, created and updated from DB. Performs authorization for data Performs validation
  • 24. Connecting GraphQL to the business logic: Resolver functions maps directly to the business logic.
  • 25. Example 1: Query Joke { joke(id: "1") { id text funnyLevel } }
  • 26. Before the split const query = { joke: { type: GraphQLJoke, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: async (root, args, context) { const data = await db.joke.findById(args.id); if (data == null) return null; /* Authorization */ const canSee = data.creator === context.viewer.id; return canSee ? data : null; } } }
  • 27. After the split import Joke from "../logic"; const query = { joke: { type: GraphQLJoke, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: (root, args, context) => Joke.gen(context.viewer, args.id) } }
  • 28. Business logic Layer const areYouOwner = (viewer: User, data) => { return viewer.id === data.creator; } class Joke { static async gen(viewer: User, id: string): Promise<?Joke> { const data = await db.joke.findById(id); if (data == null) return null; const canSee = areYouOwner(viewer, data); return canSee ? new Joke(data) : null; } constructor(data: Object) { this.id = String(data.id); this.text = data.text; this.funnyLevel = data.funnyLevel; } }
  • 29. Example 2: Mutation to update a joke mutation { updateJoke(jokeId: "1", funnyLevel: 10) { id text funnyLevel } }
  • 30. GraphQL const mutation = { type: new GraphQLNonNull(GraphQLJoke), description: "Update a joke.", args: { jokeId: { type: new GraphQLNonNull(GraphQLID) }, funnyLevel: { type: new GraphQLNonNull(GraphQLInt) } }, resolve: (root, args, context) => { //... } }
  • 31. Single source of truth for authorization import Joke from "../logic"; resolve: (root, args, context) => { /* Authorization */ const joke = Joke.gen(context.viewer, args.jokeId); if (!joke) throw new Error('No joke found for the id'); /* Performs validation and updates DB */ joke.setFunnyLevel(args.funnyLevel); return joke; }
  • 33. Bene ts Single source of truth for enforcing business rules. Testability Maintainable
  • 35. What is it? A GraphQL schema speci cation that makes strong assumptions about refetching, pagination, and realizing mutation predictability.
  • 37. Joke Query //GraphQL query: query { viewer { id jokes { id } } } //Result: { "viewer": { "id": "1", "jokes": [{ "id": "1" }] } }
  • 39. Joke Query Unique Ids //GraphQL query: query { viewer { id jokes { id } } } //Result: { "viewer": { "id": "Sh3Ee!p=", "jokes": [{ "id": "m0=nK3Y!" }] } }
  • 40. The Result Caching becomes simple Database assumptions opaque to client
  • 41. ... and every object can easily be refetched
  • 43. Retrieve resource using single query query { node(id: "E4sT3r!39g=") { id ... on Joke { title funnyness } } }
  • 45. List Example "data" { "viewer" { "jokes": [ { "id": "1", "text": "How do you make a tissue" }, ... { "id": "500", "text": "Pfooo, only half way" }, ... { "id": "1000",
  • 46. Why Pagination? More ne-grained control Prevents app from being slow Improves back-end performance
  • 47. Pagination done right using connection approach query { viewer { jokes(first: 10 /*The offset*/, after: "TUr71e=!" /*Cursor*/) { edges { cursor //Cursor node { text funnyLevel } } pageInfo { //pageInfo contains info about whether there exist more edges hasNextPage } } } }
  • 48. Opportunity to change to Relay if you wish
  • 49. Advantages Relay Compliant Schema Enforce globally unique id that is opaque Any resource that belongs to you can be retrieved using a single query Pagination for lists is built in Opportunity to change to Relay if you wish
  • 50. To Sum Up Lesson 1: API, Business Logic, Persistence Layer Lesson 2: Relay compliant schema
  • 51. More Lessons Authentication Caching & Batching Error Handling
  • 52. Reach us on twitter! @excite-engineer @Mr_Blue_Sql