SlideShare una empresa de Scribd logo
1 de 45
Descargar para leer sin conexión
GraphQL - when REST API is
not enough - lessons learned
Marcin Stachniuk
Marcin Stachniuk
mstachniuk.github.io
/mstachniuk/graphql-java-example
@MarcinStachniuk
shipkit.org
wroclaw.jug.pl
collibra.com
REST - Representational state transfer
GET
POST
PUT
DELETE
PATCH
...
https://api.example.com/customers/123
REST response
GET /customers/111
{
"customer": {
"id": "111",
"name": "John Doe",
"email": "john@doe.com",
"company": {
"id": "222"
},
"orders": [
{
"id": "333"
},
{
"id": "444"
}
]
}
}
{
"customer": {
"id": "111",
"name": "John Doe",
"email": "john@doe.com",
"company": {
"href": "https://api.example.com/companies/222"
},
"orders": [
{
"href": "https://api.example.com/orders/333"
},
{
"href": "https://api.example.com/orders/444"
}
]
}
}
REST response golden rules consequences: several roundtrips
REST response with nested data
GET /customers/111
{
"customer": {
"id": "111",
"name": "John Doe",
"email": "john@doe.com",
"company": {
"id": "222",
"name": "My Awesome Corporation",
"website": "MyAwesomeCorporation.com"
},
"orders": [
{
"id": "333",
"status": "delivered",
"items": [
{
"id": "555",
"name": "Silver Bullet",
"amount": "42",
"price": "10000000",
"currency": "USD",
"producer": {
"id": "777",
"name": "Lorem Ipsum",
"website": "LoremIpsum.com"
}
}
]
},
{
"id": "444",
"name": "Golden Hammer",
"amount": "5",
"price": "10000",
"currency": "USD",
"producer": {
...
}
}
]
}
}
REST response with nested data and limit fields
GET /customers/111?fields=name,company/*,orders.status,orders.items(name,producer/name)
{
"customer": {
"id": "111",
"name": "John Doe",
"email": "john@doe.com",
"company": {
"id": "222",
"name": "My Awesome Corporation",
"website": "MyAwesomeCorporation.com"
},
"orders": [
{
"id": "333",
"status": "delivered",
"items": [
{
"id": "555",
"name": "Silver Bullet",
"amount": "42",
"price": "10000000",
"currency": "USD",
"producer": {
"id": "777",
"name": "Lorem Ipsum",
"website": "LoremIpsum.com"
}
}
]
},
{
"id": "444",
"name": "Golden Hammer",
"amount": "5",
"price": "10000",
"currency": "USD",
"producer": {
...
}
}
]
}
}
Different clients - different needs
/web /iphone /android /tv
Application
Web iPhone Android TV
Different clients - different needs
/web /iphone /android /tv
Application
Web iPhone Android TV
Content-Type: application/vnd.myawesomecorporation.com+v1+web+json
iphone
android
tv
Different clients - different needs
/web /iphone /android /tv
Application
Web iPhone Android TV
Content-Type: application/vnd.myawesomecorporation.com+v1+web+json
iphone
android
tv
Problems at Collibra
Platform
App 1 App 2
Customer
App X...
Problems at Collibra
New Frontend Framework
ReactJS
Relay GraphQL
TypeScript
GraphQL
● Graph Query Language
● Published by Facebook in 2015
● Growth from Facebook Graph API
● Reference implementation in JavaScript
● First version of Java Library: 18 Jul 2015
● First usage: 21 Sep 2015
Lessons Learned #1
Never add a library to your project
few days after init release
● No community
● A lot of bugs
● Bad documentation
● Strict following reference implementation and specification
GraphQL main concepts
● One endpoint for all operations
● Always define in request what you need
● Queries, Mutations and Subscription
● Defined by schema (type system)
● Good developer tools
GraphQL Simple API
GET /customers/2?fields=id,name,email
type Customer {
id: ID!
name: String!
email: String!
}
type Query {
customer(id: String!): Customer!
}
{
"data": {
"customer": {
"id": "2",
"name": "name",
"email": "a@b.com"
}
}
}
{
customer(id: "2") {
id
name
email
}
}
GraphQL Simple API
GET /customers/2?fields=id,name,email,company(id,name)
type Customer {
id: ID!
name: String!
email: String!
company: Company
}
type Company {
id: ID!
name: String!
website: String!
}
type Query {
customer(id: String!): Customer!
}
{
"data": {
"customer": {
"id": "2",
"name": "name",
"email": "a@b.com",
"company": {
"id": "211",
"name": "Company Corp."
}
}
}
}
{
customer(id: "2") {
id
name
email
company {
id
name
}
}
}
GraphQL Simple API
GET /customers/2?fields=id,name,email,orders(id,status)
type Customer {
id: ID!
name: String!
email: String!
company: Company
orders: [Order]
}
type Order {
id: ID!
status: Status
}
type Status {
NEW, CANCELED, DONE
}
{
"data": {
"customer": {
"id": "22",
"name": "name",
"orders": [
{
"id": "55",
"status": "NEW"
},
{
"id": "66",
"status": "DONE"
}
]
} } }
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
How to implement DataFetcher for queries
GET /customers/2?fields=id,name,email,orders(id,status)
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
@Component
public class CustomerFetcher extends PropertyDataFetcher<Customer> {
@Autowired
private CustomerService customerService;
public CustomerFetcher() {
super("customer");
}
@Override
public Customer get(DataFetchingEnvironment environment) {
String id = environment.getArgument("id");
return customerService.getCustomerById(id);
}
}
How to implement DataFetcher for queries
GET /customers/2?fields=id,name,email,orders(id,status)
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
public class Customer {
private String id;
private String name;
private String email; // getters are not required
}
public class OrderDataFetcher extends PropertyDataFetcher<List<Order>> {
@Override
public List<Order> get(DataFetchingEnvironment environment) {
Customer source = environment.getSource();
String customerId = source.getId();
return orderService.getOrdersByCustomerId(customerId);
}
}
How to implement DataFetcher for queries
@Override
public Customer get(DataFetchingEnvironment environment) {
Object source = environment.getSource();
Object root = environment.getRoot();
if (source instanceof Customer) {
// ...
} else if (...) {
// ...
}
// ...
}
GraphQL mutations
input CreateCustomerInput {
name: String
email: String
clientMutationId: String!
}
type CreateCustomerPayload {
customer: Customer
clientMutationId: String!
}
type Mutation {
createCustomer(input: CreateCustomerInput):
CreateCustomerPayload!
}
{
"data": {
"createCustomer": {
"customer": {
"id": "40",
},
"clientMutationId": "123"
}
}
}
POST /customers
mutation {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
How to implement DataFetcher for mutations
POST /customers
mutation {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
@Override
public CreateCustomerPayload get(DataFetchingEnvironment environment) {
Map<String, Object> input = environment.getArgument("input");
String name = (String) input.get("name");
String email = (String) input.get("email");
String clientMutationId = (String) input.get("clientMutationId");
Customer customer = customerService.create(name, email);
return new CreateCustomerPayload(customer, clientMutationId);
}
Abstraction over GraphQL Java
Our abstraction
Data Fetcher 2
Pagination
Inputs mapping to objects
...
Data Fetcher 1 Data Fetcher N...
Lessons Learned #2
Abstraction is not good if you don’t understand
how it works under the hood
● A lot of copy paste errors
● Bad design of our API
● Let’s think in graphs and NOT in endpoints / resources / entities / DTO
GraphQL can do more!
● Aliases
● Fragments
● Interfaces
● Unions
● ...
GraphiQL
GraphiQL: github.com/graphql/graphiql
GraphQL type system
How to define your schema?
Code First approach
private GraphQLFieldDefinition customerDefinition() {
return GraphQLFieldDefinition.newFieldDefinition()
.name("customer")
.argument(GraphQLArgument.newArgument()
.name("id")
.type(new GraphQLNonNull(GraphQLString)))
.type(new GraphQLNonNull(GraphQLObjectType.newObject()
.name("Customer")
.field(GraphQLFieldDefinition.newFieldDefinition()
.name("id")
.description("fields with ! are requred")
.type(new GraphQLNonNull(GraphQLID))
.build())
….
.build()))
.dataFetcher(customerFetcher)
.build();
}
Code First approach - project building diagram
Typescript relay
plugin
Introspection
query
Introspection
response
Replace Relay
definitions
Schema First approach
type Customer {
# fields with ! are required
id: ID!
name: String!
email: String!
company: Company
orders: [Order]
}
SchemaParser schemaParser = new SchemaParser();
File file = // ...
TypeDefinitionRegistry registry = schemaParser.parse(file);
SchemaGenerator schemaGenerator = new SchemaGenerator();
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder ->
builder.dataFetcher("customer", customerFetcher))
// ...
.build();
return schemaGenerator.makeExecutableSchema(registry, runtimeWiring);
*.graphqls
Code First approach - project building diagram
model.graphqls
Lessons Learned #3
Schema First Approach is better
Code First approach:
● Hard to maintain
● It was the only way at the
beginning to define a schema
● No possibility to mix both
● No easy way to migrate to
Schema First - technical debt
Schema First Approach:
● Easy to maintain and
understand
● Help organise work
● Demo schema definition only
in 54 + 23 lines, instead of 173
lines
GraphQL pagination, filtering, sorting
Pagination:
● Before, after
● Offset, limit
Filtering:
● filter: {name: “Bob” email: “%@gmail.com”}
● filter: {
OR: [{
AND: [{
releaseDate_gte: "2009"
}, {
title_starts_with: "The Dark Knight"
}]
}, name: “Bob”
}
Sorting:
● orderBy: ASC, DESC
● sort: NEWEST, IMPORTANCE
Lessons Learned #4
GraphQL is not full query language
● More flexibility
● Less common conventions
● Dgraph.io created GraphQL+- extension with filtering, regular
expressions, i18n, equal/greater/less…
Assumptions enforced by Relay
● All returned types need to implement
Node interface
interface Node {
id: ID!
}● All IDs needs to be unique in whole
graph
● ID should be base64
● For pagination use PageInfo
type PageInfo {
hasNextPage: Boolean
hasPreviousPage: Boolean
# optional:
startCursor: String
endCursor: String
}
Relay mutations namings conventions
input CreateCustomerInput {
name: String
email: String
clientMutationId: String!
}
type CreateCustomerPayload {
customer: Customer
clientMutationId: String!
}
type Mutation {
createCustomer(input: CreateCustomerInput): CreateCustomerPayload!
}
N+1 problem
{
customers { 1 call
id
name
orders { n calls
id
status
}
}
}
java-dataloader
● Add async BatchLoader
● Add caching
Lessons Learned #5
If you have N + 1 problem
use java-dataloader
Testing GraphQL
@SpringBootTest
@ContextConfiguration(classes = Main)
class CustomerFetcherSpec extends Specification {
@Autowired
GraphQLSchema graphQLSchema
GraphQL graphQL
def setup() {
graphQL = GraphQL.newGraphQL(graphQLSchema).build()
}
Testing GraphQL
def "should get customer by id"() {
given:
def query = """{ customer(id: "2") { … } }"""
def expected = [ "customer": [ … ] ]
when:
def result = graphQL.execute(query)
then:
result.data == expected
}
Summary
GraphQL:
● Nice alternative to REST
● It can be used together with REST
● Good integration with Relay / ReactJS
● You get exactly what you want to get
● Good for API with different clients
● Good to use on top of existing API
● Self documented
● Easy testing
Nothing is a silver bullet
GraphQL - when REST API is
not enough - lessons learned
Marcin Stachniuk
Thankyou!

Más contenido relacionado

La actualidad más candente

Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDeclan Whelan
 
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionSimplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionVMware Tanzu
 
Html5 Interview Questions & Answers
Html5 Interview Questions & AnswersHtml5 Interview Questions & Answers
Html5 Interview Questions & AnswersRatnala Charan kumar
 
Finding the right stuff, an intro to Elasticsearch (at Rug::B)
Finding the right stuff, an intro to Elasticsearch (at Rug::B) Finding the right stuff, an intro to Elasticsearch (at Rug::B)
Finding the right stuff, an intro to Elasticsearch (at Rug::B) Michael Reinsch
 
Wcf data services
Wcf data servicesWcf data services
Wcf data servicesEyal Vardi
 
Grails Custom Tag lib
Grails Custom Tag libGrails Custom Tag lib
Grails Custom Tag libAli Tanwir
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)Carles Farré
 
Zensations Drupal 8 GraphQL Presentation 2015
Zensations Drupal 8 GraphQL Presentation 2015Zensations Drupal 8 GraphQL Presentation 2015
Zensations Drupal 8 GraphQL Presentation 2015Zensations GmbH
 
Introduction to AJAX and DWR
Introduction to AJAX and DWRIntroduction to AJAX and DWR
Introduction to AJAX and DWRSweNz FixEd
 
Evolving The Java Language
Evolving The Java LanguageEvolving The Java Language
Evolving The Java LanguageQConLondon2008
 
Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Vagif Abilov
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Jonas Follesø
 
Angular JS2 Training Session #1
Angular JS2 Training Session #1Angular JS2 Training Session #1
Angular JS2 Training Session #1Paras Mendiratta
 
Grails Internationalization
Grails   InternationalizationGrails   Internationalization
Grails Internationalizationnakul-pant
 

La actualidad más candente (19)

Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with Rails
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) ExtensionSimplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
Simplify Access to Data from Pivotal GemFire Using the GraphQL (G2QL) Extension
 
Html5 Interview Questions & Answers
Html5 Interview Questions & AnswersHtml5 Interview Questions & Answers
Html5 Interview Questions & Answers
 
Finding the right stuff, an intro to Elasticsearch (at Rug::B)
Finding the right stuff, an intro to Elasticsearch (at Rug::B) Finding the right stuff, an intro to Elasticsearch (at Rug::B)
Finding the right stuff, an intro to Elasticsearch (at Rug::B)
 
Wcf data services
Wcf data servicesWcf data services
Wcf data services
 
Grails Custom Tag lib
Grails Custom Tag libGrails Custom Tag lib
Grails Custom Tag lib
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
 
Javascript
JavascriptJavascript
Javascript
 
Java script -23jan2015
Java script -23jan2015Java script -23jan2015
Java script -23jan2015
 
Zensations Drupal 8 GraphQL Presentation 2015
Zensations Drupal 8 GraphQL Presentation 2015Zensations Drupal 8 GraphQL Presentation 2015
Zensations Drupal 8 GraphQL Presentation 2015
 
Introduction to AJAX and DWR
Introduction to AJAX and DWRIntroduction to AJAX and DWR
Introduction to AJAX and DWR
 
ajax_pdf
ajax_pdfajax_pdf
ajax_pdf
 
Evolving The Java Language
Evolving The Java LanguageEvolving The Java Language
Evolving The Java Language
 
Enter the gradle
Enter the gradleEnter the gradle
Enter the gradle
 
Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008
 
Angular JS2 Training Session #1
Angular JS2 Training Session #1Angular JS2 Training Session #1
Angular JS2 Training Session #1
 
Grails Internationalization
Grails   InternationalizationGrails   Internationalization
Grails Internationalization
 

Similar a GraphQL - when REST API is not enough - lessons learned

GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
[DevCrowd] GraphQL - gdy API RESTowe to za mało
[DevCrowd] GraphQL - gdy API RESTowe to za mało[DevCrowd] GraphQL - gdy API RESTowe to za mało
[DevCrowd] GraphQL - gdy API RESTowe to za małoMarcinStachniuk
 
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
GraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoGraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoMarcinStachniuk
 
BruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learnedBruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learnedMarcinStachniuk
 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB
 
Wroclaw GraphQL - GraphQL in Java
Wroclaw GraphQL - GraphQL in JavaWroclaw GraphQL - GraphQL in Java
Wroclaw GraphQL - GraphQL in JavaMarcinStachniuk
 
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
 
GraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageGraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageBartosz Sypytkowski
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primerBruce McPherson
 
ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
ADO.NET Entity Framework by Jose A. Blakeley and Michael PizzoADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
ADO.NET Entity Framework by Jose A. Blakeley and Michael PizzoHasnain Iqbal
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersChristopher Batey
 
Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateKiev ALT.NET
 
SQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersSQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersJerod Johnson
 

Similar a GraphQL - when REST API is not enough - lessons learned (20)

GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
[DevCrowd] GraphQL - gdy API RESTowe to za mało
[DevCrowd] GraphQL - gdy API RESTowe to za mało[DevCrowd] GraphQL - gdy API RESTowe to za mało
[DevCrowd] GraphQL - gdy API RESTowe to za mało
 
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
GraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoGraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za mało
 
BruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learnedBruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learned
 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
 
Wroclaw GraphQL - GraphQL in Java
Wroclaw GraphQL - GraphQL in JavaWroclaw GraphQL - GraphQL in Java
Wroclaw GraphQL - GraphQL in Java
 
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
 
GraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageGraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized age
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primer
 
ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
ADO.NET Entity Framework by Jose A. Blakeley and Michael PizzoADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
 
LJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java DevelopersLJC Conference 2014 Cassandra for Java Developers
LJC Conference 2014 Cassandra for Java Developers
 
Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicate
 
SQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersSQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API Consumers
 

Más de MarcinStachniuk

[WroclawJUG] Continuous Delivery in OSS using Shipkit
[WroclawJUG] Continuous Delivery in OSS using Shipkit[WroclawJUG] Continuous Delivery in OSS using Shipkit
[WroclawJUG] Continuous Delivery in OSS using ShipkitMarcinStachniuk
 
Continuous Delivery in OSS using Shipkit.org
Continuous Delivery in OSS using Shipkit.orgContinuous Delivery in OSS using Shipkit.org
Continuous Delivery in OSS using Shipkit.orgMarcinStachniuk
 
Java Web Start – jak żyć z tą dziwną technologią
Java Web Start – jak żyć z tą dziwną technologiąJava Web Start – jak żyć z tą dziwną technologią
Java Web Start – jak żyć z tą dziwną technologiąMarcinStachniuk
 
Zarządzanie zmianami w schemacie relacyjnych baz danych
Zarządzanie zmianami w schemacie relacyjnych baz danychZarządzanie zmianami w schemacie relacyjnych baz danych
Zarządzanie zmianami w schemacie relacyjnych baz danychMarcinStachniuk
 
Inicjatywa NoSQL na przykładzie db4o
Inicjatywa NoSQL na przykładzie db4oInicjatywa NoSQL na przykładzie db4o
Inicjatywa NoSQL na przykładzie db4oMarcinStachniuk
 
Automatic mechanism data migration between relational and object database
Automatic mechanism data migration between relational and object databaseAutomatic mechanism data migration between relational and object database
Automatic mechanism data migration between relational and object databaseMarcinStachniuk
 
Zastosowanie obiektowych baz danych na przykładzie db4o
Zastosowanie obiektowych baz danych na przykładzie db4oZastosowanie obiektowych baz danych na przykładzie db4o
Zastosowanie obiektowych baz danych na przykładzie db4oMarcinStachniuk
 
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017MarcinStachniuk
 
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...MarcinStachniuk
 
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...MarcinStachniuk
 
Continuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukContinuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukMarcinStachniuk
 
Zarządzanie zamianami w relacyjnych bazach danych
Zarządzanie zamianami w relacyjnych bazach danychZarządzanie zamianami w relacyjnych bazach danych
Zarządzanie zamianami w relacyjnych bazach danychMarcinStachniuk
 
Nowości w Javie 8 okiem programisty
Nowości w Javie 8 okiem programistyNowości w Javie 8 okiem programisty
Nowości w Javie 8 okiem programistyMarcinStachniuk
 
Liquibase - Zarządzanie zmianami w relacyjnych bazach danych
Liquibase - Zarządzanie zmianami w relacyjnych bazach danychLiquibase - Zarządzanie zmianami w relacyjnych bazach danych
Liquibase - Zarządzanie zmianami w relacyjnych bazach danychMarcinStachniuk
 
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...MarcinStachniuk
 
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...MarcinStachniuk
 
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.MarcinStachniuk
 
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowania
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowaniaPodstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowania
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowaniaMarcinStachniuk
 

Más de MarcinStachniuk (19)

[WroclawJUG] Continuous Delivery in OSS using Shipkit
[WroclawJUG] Continuous Delivery in OSS using Shipkit[WroclawJUG] Continuous Delivery in OSS using Shipkit
[WroclawJUG] Continuous Delivery in OSS using Shipkit
 
Continuous Delivery in OSS using Shipkit.org
Continuous Delivery in OSS using Shipkit.orgContinuous Delivery in OSS using Shipkit.org
Continuous Delivery in OSS using Shipkit.org
 
Java Web Start – jak żyć z tą dziwną technologią
Java Web Start – jak żyć z tą dziwną technologiąJava Web Start – jak żyć z tą dziwną technologią
Java Web Start – jak żyć z tą dziwną technologią
 
Zarządzanie zmianami w schemacie relacyjnych baz danych
Zarządzanie zmianami w schemacie relacyjnych baz danychZarządzanie zmianami w schemacie relacyjnych baz danych
Zarządzanie zmianami w schemacie relacyjnych baz danych
 
Inicjatywa NoSQL na przykładzie db4o
Inicjatywa NoSQL na przykładzie db4oInicjatywa NoSQL na przykładzie db4o
Inicjatywa NoSQL na przykładzie db4o
 
Automatic mechanism data migration between relational and object database
Automatic mechanism data migration between relational and object databaseAutomatic mechanism data migration between relational and object database
Automatic mechanism data migration between relational and object database
 
Zastosowanie obiektowych baz danych na przykładzie db4o
Zastosowanie obiektowych baz danych na przykładzie db4oZastosowanie obiektowych baz danych na przykładzie db4o
Zastosowanie obiektowych baz danych na przykładzie db4o
 
Wprowadzenie do J2ME
Wprowadzenie do J2MEWprowadzenie do J2ME
Wprowadzenie do J2ME
 
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017
Continuous Delivery w projekcie Open Source - Marcin Stachniuk - DevCrowd 2017
 
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...
Java Web Start czyli jak żyć z tą dziwną technologią? & Continuous Delivery w...
 
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...
Java Web Start czyli jak żyć z tą dziwną technologią & Continuous Delivery w ...
 
Continuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin StachniukContinuous delivery w projekcie open source - Marcin Stachniuk
Continuous delivery w projekcie open source - Marcin Stachniuk
 
Zarządzanie zamianami w relacyjnych bazach danych
Zarządzanie zamianami w relacyjnych bazach danychZarządzanie zamianami w relacyjnych bazach danych
Zarządzanie zamianami w relacyjnych bazach danych
 
Nowości w Javie 8 okiem programisty
Nowości w Javie 8 okiem programistyNowości w Javie 8 okiem programisty
Nowości w Javie 8 okiem programisty
 
Liquibase - Zarządzanie zmianami w relacyjnych bazach danych
Liquibase - Zarządzanie zmianami w relacyjnych bazach danychLiquibase - Zarządzanie zmianami w relacyjnych bazach danych
Liquibase - Zarządzanie zmianami w relacyjnych bazach danych
 
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
 
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
Poznaj lepiej swoje srodowisko programistyczne i zwieksz swoja produktywnosc ...
 
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.
Upieksz swoje testy! Testowanie jednostkowe dla sredniozaawansowanych.
 
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowania
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowaniaPodstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowania
Podstawy tworzenia gier w J2ME, dla początkujących adeptów sztuki programowania
 

Último

GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
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
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
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
 
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
 
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 Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
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
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...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
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 

Último (20)

GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
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...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 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
 
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
 
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 Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
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
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

GraphQL - when REST API is not enough - lessons learned

  • 1. GraphQL - when REST API is not enough - lessons learned Marcin Stachniuk
  • 3. REST - Representational state transfer GET POST PUT DELETE PATCH ... https://api.example.com/customers/123
  • 4. REST response GET /customers/111 { "customer": { "id": "111", "name": "John Doe", "email": "john@doe.com", "company": { "id": "222" }, "orders": [ { "id": "333" }, { "id": "444" } ] } } { "customer": { "id": "111", "name": "John Doe", "email": "john@doe.com", "company": { "href": "https://api.example.com/companies/222" }, "orders": [ { "href": "https://api.example.com/orders/333" }, { "href": "https://api.example.com/orders/444" } ] } }
  • 5. REST response golden rules consequences: several roundtrips
  • 6. REST response with nested data GET /customers/111 { "customer": { "id": "111", "name": "John Doe", "email": "john@doe.com", "company": { "id": "222", "name": "My Awesome Corporation", "website": "MyAwesomeCorporation.com" }, "orders": [ { "id": "333", "status": "delivered", "items": [ { "id": "555", "name": "Silver Bullet", "amount": "42", "price": "10000000", "currency": "USD", "producer": { "id": "777", "name": "Lorem Ipsum", "website": "LoremIpsum.com" } } ] }, { "id": "444", "name": "Golden Hammer", "amount": "5", "price": "10000", "currency": "USD", "producer": { ... } } ] } }
  • 7. REST response with nested data and limit fields GET /customers/111?fields=name,company/*,orders.status,orders.items(name,producer/name) { "customer": { "id": "111", "name": "John Doe", "email": "john@doe.com", "company": { "id": "222", "name": "My Awesome Corporation", "website": "MyAwesomeCorporation.com" }, "orders": [ { "id": "333", "status": "delivered", "items": [ { "id": "555", "name": "Silver Bullet", "amount": "42", "price": "10000000", "currency": "USD", "producer": { "id": "777", "name": "Lorem Ipsum", "website": "LoremIpsum.com" } } ] }, { "id": "444", "name": "Golden Hammer", "amount": "5", "price": "10000", "currency": "USD", "producer": { ... } } ] } }
  • 8. Different clients - different needs /web /iphone /android /tv Application Web iPhone Android TV
  • 9. Different clients - different needs /web /iphone /android /tv Application Web iPhone Android TV Content-Type: application/vnd.myawesomecorporation.com+v1+web+json iphone android tv
  • 10. Different clients - different needs /web /iphone /android /tv Application Web iPhone Android TV Content-Type: application/vnd.myawesomecorporation.com+v1+web+json iphone android tv
  • 11. Problems at Collibra Platform App 1 App 2 Customer App X...
  • 14. GraphQL ● Graph Query Language ● Published by Facebook in 2015 ● Growth from Facebook Graph API ● Reference implementation in JavaScript ● First version of Java Library: 18 Jul 2015 ● First usage: 21 Sep 2015
  • 15. Lessons Learned #1 Never add a library to your project few days after init release ● No community ● A lot of bugs ● Bad documentation ● Strict following reference implementation and specification
  • 16. GraphQL main concepts ● One endpoint for all operations ● Always define in request what you need ● Queries, Mutations and Subscription ● Defined by schema (type system) ● Good developer tools
  • 17. GraphQL Simple API GET /customers/2?fields=id,name,email type Customer { id: ID! name: String! email: String! } type Query { customer(id: String!): Customer! } { "data": { "customer": { "id": "2", "name": "name", "email": "a@b.com" } } } { customer(id: "2") { id name email } }
  • 18. GraphQL Simple API GET /customers/2?fields=id,name,email,company(id,name) type Customer { id: ID! name: String! email: String! company: Company } type Company { id: ID! name: String! website: String! } type Query { customer(id: String!): Customer! } { "data": { "customer": { "id": "2", "name": "name", "email": "a@b.com", "company": { "id": "211", "name": "Company Corp." } } } } { customer(id: "2") { id name email company { id name } } }
  • 19. GraphQL Simple API GET /customers/2?fields=id,name,email,orders(id,status) type Customer { id: ID! name: String! email: String! company: Company orders: [Order] } type Order { id: ID! status: Status } type Status { NEW, CANCELED, DONE } { "data": { "customer": { "id": "22", "name": "name", "orders": [ { "id": "55", "status": "NEW" }, { "id": "66", "status": "DONE" } ] } } } { customer(id: "2") { id name orders { id status } } }
  • 20. How to implement DataFetcher for queries GET /customers/2?fields=id,name,email,orders(id,status) { customer(id: "2") { id name orders { id status } } } @Component public class CustomerFetcher extends PropertyDataFetcher<Customer> { @Autowired private CustomerService customerService; public CustomerFetcher() { super("customer"); } @Override public Customer get(DataFetchingEnvironment environment) { String id = environment.getArgument("id"); return customerService.getCustomerById(id); } }
  • 21. How to implement DataFetcher for queries GET /customers/2?fields=id,name,email,orders(id,status) { customer(id: "2") { id name orders { id status } } } public class Customer { private String id; private String name; private String email; // getters are not required } public class OrderDataFetcher extends PropertyDataFetcher<List<Order>> { @Override public List<Order> get(DataFetchingEnvironment environment) { Customer source = environment.getSource(); String customerId = source.getId(); return orderService.getOrdersByCustomerId(customerId); } }
  • 22. How to implement DataFetcher for queries @Override public Customer get(DataFetchingEnvironment environment) { Object source = environment.getSource(); Object root = environment.getRoot(); if (source instanceof Customer) { // ... } else if (...) { // ... } // ... }
  • 23. GraphQL mutations input CreateCustomerInput { name: String email: String clientMutationId: String! } type CreateCustomerPayload { customer: Customer clientMutationId: String! } type Mutation { createCustomer(input: CreateCustomerInput): CreateCustomerPayload! } { "data": { "createCustomer": { "customer": { "id": "40", }, "clientMutationId": "123" } } } POST /customers mutation { createCustomer(input: { name: "MyName" email: "me@me.com" clientMutationId: "123" }) { customer { id } clientMutationId } }
  • 24. How to implement DataFetcher for mutations POST /customers mutation { createCustomer(input: { name: "MyName" email: "me@me.com" clientMutationId: "123" }) { customer { id } clientMutationId } } @Override public CreateCustomerPayload get(DataFetchingEnvironment environment) { Map<String, Object> input = environment.getArgument("input"); String name = (String) input.get("name"); String email = (String) input.get("email"); String clientMutationId = (String) input.get("clientMutationId"); Customer customer = customerService.create(name, email); return new CreateCustomerPayload(customer, clientMutationId); }
  • 25. Abstraction over GraphQL Java Our abstraction Data Fetcher 2 Pagination Inputs mapping to objects ... Data Fetcher 1 Data Fetcher N...
  • 26. Lessons Learned #2 Abstraction is not good if you don’t understand how it works under the hood ● A lot of copy paste errors ● Bad design of our API ● Let’s think in graphs and NOT in endpoints / resources / entities / DTO
  • 27. GraphQL can do more! ● Aliases ● Fragments ● Interfaces ● Unions ● ...
  • 29. GraphQL type system How to define your schema?
  • 30. Code First approach private GraphQLFieldDefinition customerDefinition() { return GraphQLFieldDefinition.newFieldDefinition() .name("customer") .argument(GraphQLArgument.newArgument() .name("id") .type(new GraphQLNonNull(GraphQLString))) .type(new GraphQLNonNull(GraphQLObjectType.newObject() .name("Customer") .field(GraphQLFieldDefinition.newFieldDefinition() .name("id") .description("fields with ! are requred") .type(new GraphQLNonNull(GraphQLID)) .build()) …. .build())) .dataFetcher(customerFetcher) .build(); }
  • 31. Code First approach - project building diagram Typescript relay plugin Introspection query Introspection response Replace Relay definitions
  • 32. Schema First approach type Customer { # fields with ! are required id: ID! name: String! email: String! company: Company orders: [Order] } SchemaParser schemaParser = new SchemaParser(); File file = // ... TypeDefinitionRegistry registry = schemaParser.parse(file); SchemaGenerator schemaGenerator = new SchemaGenerator(); RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() .type("Query", builder -> builder.dataFetcher("customer", customerFetcher)) // ... .build(); return schemaGenerator.makeExecutableSchema(registry, runtimeWiring); *.graphqls
  • 33. Code First approach - project building diagram model.graphqls
  • 34. Lessons Learned #3 Schema First Approach is better Code First approach: ● Hard to maintain ● It was the only way at the beginning to define a schema ● No possibility to mix both ● No easy way to migrate to Schema First - technical debt Schema First Approach: ● Easy to maintain and understand ● Help organise work ● Demo schema definition only in 54 + 23 lines, instead of 173 lines
  • 35. GraphQL pagination, filtering, sorting Pagination: ● Before, after ● Offset, limit Filtering: ● filter: {name: “Bob” email: “%@gmail.com”} ● filter: { OR: [{ AND: [{ releaseDate_gte: "2009" }, { title_starts_with: "The Dark Knight" }] }, name: “Bob” } Sorting: ● orderBy: ASC, DESC ● sort: NEWEST, IMPORTANCE
  • 36. Lessons Learned #4 GraphQL is not full query language ● More flexibility ● Less common conventions ● Dgraph.io created GraphQL+- extension with filtering, regular expressions, i18n, equal/greater/less…
  • 37. Assumptions enforced by Relay ● All returned types need to implement Node interface interface Node { id: ID! }● All IDs needs to be unique in whole graph ● ID should be base64 ● For pagination use PageInfo type PageInfo { hasNextPage: Boolean hasPreviousPage: Boolean # optional: startCursor: String endCursor: String }
  • 38. Relay mutations namings conventions input CreateCustomerInput { name: String email: String clientMutationId: String! } type CreateCustomerPayload { customer: Customer clientMutationId: String! } type Mutation { createCustomer(input: CreateCustomerInput): CreateCustomerPayload! }
  • 39. N+1 problem { customers { 1 call id name orders { n calls id status } } } java-dataloader ● Add async BatchLoader ● Add caching
  • 40. Lessons Learned #5 If you have N + 1 problem use java-dataloader
  • 41. Testing GraphQL @SpringBootTest @ContextConfiguration(classes = Main) class CustomerFetcherSpec extends Specification { @Autowired GraphQLSchema graphQLSchema GraphQL graphQL def setup() { graphQL = GraphQL.newGraphQL(graphQLSchema).build() }
  • 42. Testing GraphQL def "should get customer by id"() { given: def query = """{ customer(id: "2") { … } }""" def expected = [ "customer": [ … ] ] when: def result = graphQL.execute(query) then: result.data == expected }
  • 43. Summary GraphQL: ● Nice alternative to REST ● It can be used together with REST ● Good integration with Relay / ReactJS ● You get exactly what you want to get ● Good for API with different clients ● Good to use on top of existing API ● Self documented ● Easy testing
  • 44. Nothing is a silver bullet
  • 45. GraphQL - when REST API is not enough - lessons learned Marcin Stachniuk Thankyou!