Wszyscy znamy i tworzymy API RESTowe. Jednak to podejście ma swoje wady i ograniczenia. Dlatego Facebook stworzył GraphQL jako alternatywę. W mojej prezentacji przedstawię problemy RESTa oraz jak je rozwiązuje GraphQL. Pokażę składnię, jak projektować takie API oraz zalety i wady.
3. What is NOT GraphQL
GraphQL =/= Graph (math)
GraphQL =/= GQL Standard
GraphQL =/= openCypher, PGQL, GSQL, and G-CORE
GraphQL =/= DQL (GraphQL+-) in Dgraph
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
4. What is GraphQL
GraphQL == language for API
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
5. Who is using REST?
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
6. REST - REpresentational State Transfer
https://api.example.com/customers/123
DELETE
PUT
POST
GET
PATCH
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
8. Different clients - different needs
Application
Web iPhone Android TV
Independent
deploym
ent
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
9. REST fixed 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"
}
]
}
}
RE
ST
Easy
selectw
hat
you
need
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
10. REST consequences: several roundtrips
U
nderFetching
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
12. REST API Versioning
GET /v2/customers/111RE
ST
GET /customers/111?v=v2RE
ST
GET /customers/111 Accept header: application/vnd.myapp.2+jsonRE
ST
GET /customers/111 Custom header: x-ms-version:2RE
ST
A
PIversioning
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
13. REST API as independent resources
GET /customersRE
ST
GET /usersRE
ST
GET /ordersRE
ST
GET /itemsRE
ST
RE
ST GET /companies
D
istorted
reality
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
14. Platform Architecture - How to define a good API?
Platform
App 1 App 2
Customer
App X...
G
ood
A
PIforall
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
15. 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
https://github.com/graphql-java/graphql-java
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
16. GraphQL main concepts
● One endpoint for all operations
● Always define in request what you need
● Queries, Mutations and Subscriptions
● Defined by schema
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
17. Data is a graph
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
18. GraphQL time for demo
● Fragments
● Aliases
● Directives
● Interfaces
● Unions
● Query
● Syntax Error
● Mutation
● Operation name
● Variables
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
19. GraphQL Simple API
GET /customers/2?fields=id,name,email
type Customer {
#fields with ! are not null
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
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
20. GraphQL Bad Request
GET /custo!@#$ -> 404
{
"data": null,
"errors": [
{
"message": "Invalid Syntax",
"locations": [
{
"line": 2,
"column": 8
}
],
"errorType": "InvalidSyntax",
"path": null,
"extensions": null
} ] }
{
custo!@#$
}
RE
ST
http.cat/200
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
21. Go back to the roots
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
22. 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
}
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
23. 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
}
enum Status {
NEW, CANCELED, DONE
}
{
"data": {
"customer": {
"id": "2",
"name": "name",
"orders": [
{
"id": "55",
"status": "NEW"
},
{
"id": "66",
"status": "DONE"
}
] } } }
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
24. GraphQL Aliases
GET /customers/2?fields=id,name,email +
{
"data": {
"cust1": {
"id": "2",
"name": "name",
"email": "a@b.com"
},
"cust2": {
"id": "3",
"name": "John Doe",
"email": "john@doe.com"
}
}
}
query get2Cust {
cust1: customer(id: "2") {
id
name
email
}
cust2: customer(id: "3") {
id
name
email
}
}
RE
ST GET /customers/3?fields=id,name,emailRE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
25. GraphQL Fragment
GET /customers/2?fields=id,name,email +
{
"data": {
"cust1": {
"id": "2",
"name": "name",
"email": "a@b.com"
},
"cust2": {
"id": "3",
"name": "John Doe",
"email": "john@doe.com"
}
}
}
query get2Cust {
cust1: customer(id: "2") {
... frag1
}
cust2: customer(id: "3") {
... frag1
}
}
fragment frag1 on Customer {
id
name
email
}
RE
ST GET /customers/3?fields=id,name,emailRE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
26. GraphQL Arguments
GET /customers/2?fields=id,name,email +
{
"data": {
"cust1": {
"id": "2",
"name": "name",
"email": "a@b.com"
},
"cust2": {
"id": "3",
"name": "John Doe",
"email": "john@doe.com"
}
}
}
query get2Cust($arg1:String!, $arg2: String!) {
cust2: customer(id: $arg1) {
... frag1
}
cust3: customer(id: $arg2) {
... frag1
}
}
fragment frag1 on Customer {
id
name
email
}
RE
ST GET /customers/3?fields=id,name,emailRE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
27. GraphQL Directive
GET /customers/2?fields=id,name
{
"data": {
"customer": {
"id": "2",
"name": "name"
}
}
}
query getCust ($showEmail: Boolean!) {
customer(id: "2") {
id
name
email @include(if: $showEmail)
}
}
{
"showEmail": false
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
28. GraphQL Interface
GET /users?fields=id,name,superAdmin,permissions
type Query {
users: [User]
}
interface User {
id: ID!
name: String!
email: String!
}
type Admin implements User {
superAdmin: Boolean! // + id...
}
type Moderator implements User {
permissions: [String] // + id...
}
{
"data": {
"users": [
{
"id": "777",
"name": "Admin a",
"superAdmin": true
},
{
"id": "888",
"name": "Moderator",
"permissions": [
"Delete Customer",
"Delete comment"
]}]}}
query getUsers {
users {
... on Admin {
id
name
superAdmin
}
... on Moderator {
id
name
permissions
}
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
29. GraphQL Union
GET /search?input=a?fields=typename,name
type Query {
search(input: String):
[SearchResult]
}
union SearchResult =
Customer |
Admin |
Moderator
{
"data": {
"search": [
{
"__typename": "Customer",
"name": "name"
},
{
"__typename": "Admin",
"name": "Admin a"
},
{
"__typename": "Moderator",
"name": "Moderator"
}]}}
query searchSmth {
search(input: "a") {
__typename
... on Customer {
name
}
... on Admin {
name
}
... on Moderator {
name
}
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
30. 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 PUT /customers/123 DELETE /customers/123 PATCH /customers/123
mutation {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
RE
ST
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
31. GraphQL mutations + operation name
mutation crCust {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
{
"data": {
"createCustomer": {
"customer": {
"id": "40",
},
"clientMutationId":
"123"
}
}
}
POST /customers PUT /customers/123 DELETE /customers/123 PATCH /customers/123RE
ST
mutation {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
33. GraphQL Java implementations
How to implement GraphQL in Java?
/graphql-java/graphql-java
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
34. GraphQL type system
How to define your schema?
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
35. Code First approach / programmatically
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 not null")
.type(new GraphQLNonNull(GraphQLID))
.build())
….
.build()))
.dataFetcher(customerFetcher)
.build();
}
Schema First approach
type Query {
customer(id: String!): Customer!
}
type Customer {
#fields with ! are not null
id: ID!
name: String!
email: String!
company: Company
orders: [Order]
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
36. Schema First approach
type Customer {
# fields with ! are required
id: ID!
name: String!
email: String!
company: Company
orders: [Order]
}
*.graphqls
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);
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
38. SPQR approach
public class UserService {
@GraphQLQuery(name = "user")
public User getById(@GraphQLArgument(name = "id") Integer id) {
//...
}
}
public class User {
//...
@GraphQLQuery(name = "name", description = "A person's name")
public String getName() {
return name;
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
39. SPQR approach - Smart conventions
@GraphQLType(name = "Item")
public class SpqrItem {
private String id;
private int amount;
// ...
@GraphQLId
@GraphQLNonNull
@GraphQLQuery(name = "id", description = "Item id")
public String getId() {
return id;
}
public int getAmount() {
return amount;
}
}
// 'ID' type in schema, add 'implements Node'
// add ! (non null) in schema
// optional
// add ! (non null) because it’s int
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
40. Classic Code First Approach
Pros:
● Stable library
● Some Javadoc and
documentation
● It was the only way at the
beginning in Java to define a
schema
Cons:
● Hard to maintain
● Missing big picture
● Backend part needs to be
implemented first
● One DataFetcher for one
operation
● No possibility to mix with
Schema First
● No easy way to migrate to
Schema First or SPQR
● Javadoc could be better
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
41. Schema First Approach
Pros:
● Easy to maintain
● Stable library
● Some Javadoc and
documentation
● Easy DSL to understand and
maintain
● Reduce boilerplate to write
● A possibility to split schema into
more files
● Parallel development (frontend &
backend)
Cons:
● Possible mismatch between
types in schema file and Java
code
● Binding between operations
defined in schema and
DataFetcher's is needed
● One DataFetcher for one
operation
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
42. SPQR Approach
Pros:
● The author replied to Github
issues quickly
● Reduce boilerplate to write
● No mismatch between Schema
and Java code
● No binding between schema and
DataFetchers is needed
● Smart conventions
Cons:
● Development is frozen for now
● Production ready?
● Zero Javadoc or other
documentation
● Missing big picture
● Backend part needs to be
implemented first
● Ugly names for generics:
MutationPayload<User> =>
MutationPayload_User
● Hard to change smart
conventions
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
43. Schema is ready, what’s next?
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
44. How to implement DataFetcher for queries
GET /customers/2?fields=id,name,email,orders(id,status)
@Component
public class CustomerFetcher extends PropertyDataFetcher<Customer> {
@Autowired
private CustomerService customerService;
@Override
public Customer get(DataFetchingEnvironment environment) {
String id = environment.getArgument("id");
return customerService.getCustomerById(id);
}
}
RE
ST
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
45. How to implement DataFetcher for queries
GET /customers/2?fields=id,name,email,orders(id,status)
public class Customer {
private String id;
private String name;
private String email; // getters are not required
}
RE
ST
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
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);
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
46. How to implement DataFetcher for mutations
POST /customers PUT /customers/123 DELETE /customers/123 PATCH /customers/123
@Component
public class CreateCustomersFetcher extends
PropertyDataFetcher<CreateCustomersPayload> {
@Override
public CreateCustomerPayload get(DataFetchingEnvironment env) {
Map<String, Object> input = env.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);
}
RE
ST
mutation {
createCustomer(input: {
name: "MyName"
email: "me@me.com"
clientMutationId: "123"
}) {
customer {
id
}
clientMutationId
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
47. In case Interfaces and Unions - Type Resolver is needed
public class UserTypeResolver implements TypeResolver {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
Object javaObject = env.getObject();
if (javaObject instanceof Admin) {
return env.getSchema().getObjectType("Admin");
} else if (javaObject instanceof Moderator) {
return env.getSchema().getObjectType("Moderator");
} else {
throw new RuntimeException("Unknown type " + javaObject.getClass().getName());
}
}
}
public interface User {...}
public class Admin implements User {...}
public class Moderator implements User {...}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
51. GraphQL downsides: N+1 problem
{
customers { 1 call
id
name
orders { n calls
id
status
}
}
}
java-dataloader
● Add async BatchLoader
● Add caching
graphQL = GraphQL.newGraphQL(schema)
.queryExecutionStrategy(
new BatchedExecutionStrategy())
.build();
+ @Batched in DataFetcher#get()
New way: https://www.graphql-java.com/documentation/v16/batching/
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
52. Complex Queries
fragment Friends on Friend {
id
name
friends {
id
name
friends {
id
name
...
}
}
}
graphQL = GraphQL.newGraphQL(schema)
.instrumentation(
new ChainedInstrumentation(asList(
new MaxQueryComplexityInstrumentation(20),
new MaxQueryDepthInstrumentation(2)
)))
.build();
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
53. GraphQL downsides: Bad GraphQL API definition - examples
{
customer(id: "2") { … }
customerFull(id: "2") { … }
customerFull2(id: "2") { … }
customerWithDetails(id: "2") { … }
...
}
{
customer(id: "2") {
id
name
orders {
id
status
}
}
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
54. GraphQL downsides: Bad GraphQL API definition - examples
{
orders (input: {
status: "NEW"
first: "2"
offset: "3"
}, first: "1", offset: "3") {
Items { … }
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
55. GraphQL downsides: Bad GraphQL API definition - examples
Relay Cursor Connections Specification section 5 (PageInfo)
type PageInfo {
hasNextPage: Boolean
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
59. 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
}
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
60. Testing is easy
Trap Adventure 2 - "The Hardest Retro Game"
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
61. Versioning
GraphQL takes a strong opinion on avoiding
versioning by providing the tools for the
continuous evolution of a GraphQL schema.
Src: https://graphql.org/learn/best-practices/#versioning
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
62. Versioning
type Query {
customer(id: String!): Customer! @deprecated(reason: "not used ...")
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
63. Versioning
Versioning is not a problem
GET /v2/customers/111RE
ST
GET /customers/111?v=v2RE
ST
GET /customers/111 Accept header: application/vnd.myapp.2+jsonRE
ST
GET /customers/111 Custom header: x-ms-version:2RE
ST
Versioning problem is different
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
68. More libraries and projects related to graphql-java
https://github.com/graphql-java/awesome-graphql-java
● JPA Implementation of GraphQL (builds on graphql-java)
● And more examples
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
69. More libraries and projects related to graphql-java
https://github.com/Netflix/dgs-framework
● GraphQL Made Easy for Spring Boot
● Build a full-featured GraphQL server with Java or Kotlin in
record time
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
70. Apollo
Build a universal GraphQL API on top of your existing REST
APIs, so you can ship new application features fast without
waiting on backend changes.
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
71. Prisma.io
Building a GraphQL server with Prisma
● Solves N+1 Problem with built-in dataloader
● No boilerplate for CRUD, filters, pagination & more
● Easily implement GraphQL subscriptions
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
72. GraphQL Inspector
GraphQL Inspector outputs a list of changes between two
GraphQL schemas. Every change is precisely explained and
marked as breaking, non-breaking or dangerous.
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
73. Tooling
Tooling is nice now
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
74. Who is using GraphQL
● GitHub: https://docs.github.com/en/free-pro-team@latest/graphql
● Netflix about Federation:
https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-
federation-part-1-ae3557c187e2
● Shopify: https://shopify.dev/docs/admin-api/graphql/reference
@MarcinStachniuk@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
75. Good practices
● Create handy schema for frontend
● Always generate GraphQL Schema and commit into your repository
● Validate your schema
● Do not use classic code first or SPQR approach to define schema
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
76. Technology Radar - GraphQL
GraphQL
● APR 2016 ASSESS
● NOV 2016 ASSESS
● NOV 2019 ASSESS
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
Src: https://www.thoughtworks.com/radar/languages-and-frameworks/graphql
77. Technology Radar - GraphQL
… misuse of this framework [...] Examples include performance gotchas
around N+1 queries and lots of boilerplate code needed when adding new
models, leading to complexity. There are workarounds to these gotchas
such as query caching...
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
Src: https://www.thoughtworks.com/radar/languages-and-frameworks/graphql
78. Technology Radar - GraphQL for server-side resource aggregation
GraphQL for server-side resource aggregation
● MAY 2018 ASSESS
● MAY 2020 TRIAL
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
Src: https://www.thoughtworks.com/radar/techniques/graphql-for-server-side-resource-aggregation
79. Technology Radar - GraphQL for server-side resource aggregation
we caution against misusing GraphQL, especially when turning it into a
server-to-server protocol. Our practice is to use GraphQL for server-side
resource aggregation only.
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
Src: https://www.thoughtworks.com/radar/techniques/graphql-for-server-side-resource-aggregation
80. Summary
GraphQL Pros:
● 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
● Nice tooling
● Thin layer
GraphQL Cons:
● High entry barrier
● Hard to return simple Map
● Not well know (yet)
● Performance overhead
● A lot of similar code to write
● No Operation Idempotency
● No Cache & Security
● No Authorisation
● Always HTTP 200 -
unsupported tools
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy
81. Take away
● https://stachniuk.com/talks/
● https://github.com/mstachniuk/graphql-java-example
● https://www.nurkiewicz.com/2019/10/graphql-server-in-java-part-i-basics.
html
@MarcinStachniukGraphQL - piękne API w Twojej aplikacjiKrakowGraphAcademy