SlideShare a Scribd company logo
1 of 50
Download to read offline
GraphQL in Java
Marcin Stachniuk
stachniuk.com
/mstachniuk/graphql-java-example
@MarcinStachniuk
wroclaw.jug.pl
shipkit.org
Our technology stack
ReactJS
Relay GraphQL
TypeScript
@MarcinStachniukGraphQL in Java
GraphQL Java implementations
How to implement GraphQL in Java?
@MarcinStachniuk
/graphql-java/graphql-java
Code First
GraphQL in Java
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 in Java
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 not null")
.type(new GraphQLNonNull(GraphQLID))
.build())
….
.build()))
.dataFetcher(customerFetcher)
.build();
}
@MarcinStachniukGraphQL in Java
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 in Java
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
}
}
}
@MarcinStachniuk
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);
}
}
GraphQL in Java
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 in Java
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 in Java
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",
"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 in Java
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 in Java
Glue everything together
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Query", builder ->
builder.dataFetcher("customer", customerFetcher))
.type("Mutation", builder ->
builder.dataFetcher("createCustomer", createCustomerFetcher))
.type(newTypeWiring("User")
.typeResolver(new UserTypeResolver())
.build())
...
.build();
@MarcinStachniukGraphQL in Java
Code First approach - How to build
Introspection
query
Introspection
response
Replace Relay
definitions
@MarcinStachniuk
Typescript relay
plugin
GraphQL in Java
GraphQL Java implementations
How to implement GraphQL in Java?
@MarcinStachniuk
/graphql-java/graphql-java
Schema First
GraphQL in Java
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 in Java
Schema First approach in comparison to Code First
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 in Java
Schema First approach - How to build
model.graphqls
@MarcinStachniukGraphQL in Java
GraphQL SPQR
@MarcinStachniuk
/leangen/graphql-spqr
Senātus Populusque Rōmānus
The Roman Senate and People
pronounced like speaker
GraphQL in Java
SPQR approach
public class UserService {
@GraphQLQuery(name = "user")
public User getById(@GraphQLArgument(name = "id") Integer id) {
//...
}
}
@MarcinStachniuk
type Query {
user(id: Int): User
}
GraphQL in Java
By default argument names will be arg0, arg1,...
You can use @GraphQLArgument or
Compile code with -parameters option
SPQR approach
public class User {
//...
@GraphQLQuery(name = "name", description = "A person's name")
public String getName() {
return name;
}
}
@MarcinStachniuk
type User {
# A person's name
name: String
}
GraphQL in Java
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;
}
}
@MarcinStachniuk
// 'ID' type in schema, add 'implements Node'
// add ! (non null) in schema
// optional
// add ! (non null) because it’s int
GraphQL in Java
Classic Code First Approach
Pros:
● Stable library
● Some Javadoc and
documentation
● It was the only way at the
beginning to define a schema
@MarcinStachniuk
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
GraphQL in Java
Schema First Approach
Pros:
● Easy to maintain and understand
● Stable library
● Some Javadoc and
documentation
● DSL defined in specification
● Reduce boilerplate to write
● A possibility to split schema into
more files
● Parallel development (frontend &
backend)
@MarcinStachniuk
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
GraphQL in Java
SPQR Approach
Pros:
● The author reply to Github issues
quickly
● Reduce boilerplate to write
● No mismatch between Schema
and Java code
● No binding between schema and
DataFetchers is needed
● Many “DataFetchers” in single
class
● Smart Relay conventions
@MarcinStachniuk
Cons:
● 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
GraphQL in Java
What to choose?
Classic Code First Approach is the worst
@MarcinStachniuk
● Big project
● High risk project
● Old project
● Small project
● Low risk project
● New Project
?
GraphQL in Java
Prisma version?
@MarcinStachniukGraphQL in Java
https://www.prisma.io/blog/the-problems-of-schema-first-graphql-developm
ent-x1mn4cb0tyl3
Alternatives out of scope this presentation
@MarcinStachniukGraphQL in Java
● GraphQL Java Tools
https://github.com/graphql-java-kickstart/graphql-java-tools
● graphql-spring-boot-starter
https://github.com/graphql-java-kickstart/graphql-spring-boot
● Micronaut GraphQL
https://github.com/micronaut-projects/micronaut-graphql
● graphql-kotlin https://github.com/ExpediaGroup/graphql-kotlin
● KGraphQL https://github.com/aPureBase/KGraphQL
● Sangria https://sangria-graphql.org/
● Lacinia https://github.com/walmartlabs/lacinia
● Gorm GraphQL https://github.com/grails/gorm-graphql/
● GQL https://grooviter.github.io/gql/
GraphQL Testing
@MarcinStachniukGraphQL in Java
Testing GraphQL
@SpringBootTest
@ContextConfiguration(classes = Main)
class CustomerFetcherSpec extends Specification {
@Autowired
GraphQLSchema graphQLSchema
GraphQL graphQL
def setup() {
graphQL = GraphQL.newGraphQL(graphQLSchema).build()
}
@MarcinStachniukGraphQL in Java
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 in Java
Versioning
type Query {
customer(id: String!): Customer! @deprecated(reason: "not used ...")
@MarcinStachniukGraphQL in Java
Extras
@MarcinStachniuk
Extras
(challenges, tools, good practices)
GraphQL in Java
From Code First to Schema First migration
https://github.com/mstachniuk/graphql-schema-from-introspection-generator
@MarcinStachniukGraphQL in Java
From Code First to Schema First migration alternatives
● In graphql-java - see: IntrospectionResultToSchema
● In graphql-js:
const graphql = require("graphql");
const schema = require("path/to/schema.json");
const clientSchema = graphql.buildClientSchema(schema.data);
const schemaString = graphql.printSchema(clientSchema);
console.log(schemaString)
@MarcinStachniukGraphQL in Java
GraphQL downsides: N+1 problem
{
customers { 1 call
id
name
orders { n calls
id
status
}
}
}
java-dataloader
● Add async BatchLoader
● Add caching
@MarcinStachniuk
graphQL = GraphQL.newGraphQL(schema)
.queryExecutionStrategy(
new BatchedExecutionStrategy())
.build();
+ @Batched in DataFetcher#get()
GraphQL in Java
GraphQL downsides: N+1 problem
If you have N + 1 problem
use java-dataloader
@MarcinStachniukGraphQL in Java
Complex Queries
fragment Friends on Friend {
id
name
friends {
id
name
friends {
id
name
...
}
}
}
@MarcinStachniuk
graphQL = GraphQL.newGraphQL(schema)
.instrumentation(
new ChainedInstrumentation(asList(
new MaxQueryComplexityInstrumentation(20),
new MaxQueryDepthInstrumentation(2)
)))
.build();
GraphQL in Java
Complex Queries
Performance killer?
Define instrumentation!
@MarcinStachniukGraphQL in Java
Recommended tools
@MarcinStachniukGraphQL in Java
Recommended tools: GraphiQL
@MarcinStachniukGraphQL in Java
Recommended tools: Altair GraphQL Client
@MarcinStachniukGraphQL in Java
https://altair.sirmuel.design/
Recommended tools: Relay
@MarcinStachniukGraphQL in Java @MarcinStachniuk
user(...) {
photo(width: "120", height: "120")
}
user(...) {
name
}
user(...) {
email
}
user(...) {
name
email
photo(width: "120", height: "120")
}
GraphQL in Java
Recommended tools: GraphQL schema linter
https://github.com/cjoudrey/graphql-schema-linter
Validate GraphQL schema definitions against a set of rules
@MarcinStachniukGraphQL in Java
Recommended tools: Graphql network - Chrome extension
@MarcinStachniuk
https://chrome.google.com/webstore/detail/graphql-network/ool
bobjfnfdnpgjcaphejlodpbefhmbn
GraphQL in Java
Recommended tools: Graphql network - Chrome extension
@MarcinStachniukGraphQL in Java
More libraries and projects related to graphql-java
https://github.com/graphql-java/awesome-graphql-java
@MarcinStachniukGraphQL in Java
Good practices
● Always generate GraphQL Schema and commit into your repository
● Follow conventions (e.g. Relay)
● Validate your schema
● Do not use classic code first approach to define schema
@MarcinStachniukGraphQL in Java
Q&A
@MarcinStachniukGraphQL in Java
GraphQL in Java
hank
you!

More Related Content

What's hot

What's hot (20)

GraphQL Introduction
GraphQL IntroductionGraphQL Introduction
GraphQL Introduction
 
An intro to GraphQL
An intro to GraphQLAn intro to GraphQL
An intro to GraphQL
 
GraphQL
GraphQLGraphQL
GraphQL
 
Graphql Intro (Tutorial and Example)
Graphql Intro (Tutorial and Example)Graphql Intro (Tutorial and Example)
Graphql Intro (Tutorial and Example)
 
GraphQL Fundamentals
GraphQL FundamentalsGraphQL Fundamentals
GraphQL Fundamentals
 
GraphQL as an alternative approach to REST (as presented at Java2Days/CodeMon...
GraphQL as an alternative approach to REST (as presented at Java2Days/CodeMon...GraphQL as an alternative approach to REST (as presented at Java2Days/CodeMon...
GraphQL as an alternative approach to REST (as presented at Java2Days/CodeMon...
 
Graphql
GraphqlGraphql
Graphql
 
GraphQL
GraphQLGraphQL
GraphQL
 
How to GraphQL
How to GraphQLHow to GraphQL
How to GraphQL
 
How to GraphQL: React Apollo
How to GraphQL: React ApolloHow to GraphQL: React Apollo
How to GraphQL: React Apollo
 
Introduction to graphQL
Introduction to graphQLIntroduction to graphQL
Introduction to graphQL
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
GraphQL: Enabling a new generation of API developer tools
GraphQL: Enabling a new generation of API developer toolsGraphQL: Enabling a new generation of API developer tools
GraphQL: Enabling a new generation of API developer tools
 
Spring GraphQL
Spring GraphQLSpring GraphQL
Spring GraphQL
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)
Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)
Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)
 
GraphQL API Gateway and microservices
GraphQL API Gateway and microservicesGraphQL API Gateway and microservices
GraphQL API Gateway and microservices
 
Introduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SFIntroduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SF
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
Getting Started with Spring for GraphQL
Getting Started with Spring for GraphQLGetting Started with Spring for GraphQL
Getting Started with Spring for GraphQL
 

Similar to Wroclaw GraphQL - GraphQL in Java

Easy data-with-spring-data-jpa
Easy data-with-spring-data-jpaEasy data-with-spring-data-jpa
Easy data-with-spring-data-jpa
Staples
 

Similar to Wroclaw GraphQL - GraphQL in Java (20)

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
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from Scratch
 
Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"
 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and Apollo
 
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 - Piękne API w Twojej Aplikacji - KrakowGraphAcademy
GraphQL - Piękne API w Twojej Aplikacji - KrakowGraphAcademyGraphQL - Piękne API w Twojej Aplikacji - KrakowGraphAcademy
GraphQL - Piękne API w Twojej Aplikacji - KrakowGraphAcademy
 
GraphQL, Redux, and React
GraphQL, Redux, and ReactGraphQL, Redux, and React
GraphQL, Redux, and React
 
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
 
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Managing GraphQL servers  with AWS Fargate & Prisma CloudManaging GraphQL servers  with AWS Fargate & Prisma Cloud
Managing GraphQL servers with AWS Fargate & Prisma Cloud
 
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
 
Easy data-with-spring-data-jpa
Easy data-with-spring-data-jpaEasy data-with-spring-data-jpa
Easy data-with-spring-data-jpa
 
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
 
Spring data requery
Spring data requerySpring data requery
Spring data requery
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
Overview of GraphQL & Clients
Overview of GraphQL & ClientsOverview of GraphQL & Clients
Overview of GraphQL & Clients
 
Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]Rapid development tools for java ee 8 [tut2998]
Rapid development tools for java ee 8 [tut2998]
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
 
Rapid Development Tools for Java EE 8 [TUT2998]
Rapid Development Tools for Java EE 8 [TUT2998]Rapid Development Tools for Java EE 8 [TUT2998]
Rapid Development Tools for Java EE 8 [TUT2998]
 
droidparts
droidpartsdroidparts
droidparts
 

More from MarcinStachniuk

More from MarcinStachniuk (20)

[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
 
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
 
[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
 
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
 
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
 

Recently uploaded

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 

Recently uploaded (20)

%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 

Wroclaw GraphQL - GraphQL in Java

  • 3. Our technology stack ReactJS Relay GraphQL TypeScript @MarcinStachniukGraphQL in Java
  • 4. GraphQL Java implementations How to implement GraphQL in Java? @MarcinStachniuk /graphql-java/graphql-java Code First GraphQL in Java
  • 5. 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 in Java
  • 6. 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 not null") .type(new GraphQLNonNull(GraphQLID)) .build()) …. .build())) .dataFetcher(customerFetcher) .build(); } @MarcinStachniukGraphQL in Java
  • 7. 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 in Java
  • 8. 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 } } } @MarcinStachniuk 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); } } GraphQL in Java
  • 9. 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 in Java
  • 10. 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 in Java
  • 11. 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", "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 in Java
  • 12. 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 in Java
  • 13. Glue everything together RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() .type("Query", builder -> builder.dataFetcher("customer", customerFetcher)) .type("Mutation", builder -> builder.dataFetcher("createCustomer", createCustomerFetcher)) .type(newTypeWiring("User") .typeResolver(new UserTypeResolver()) .build()) ... .build(); @MarcinStachniukGraphQL in Java
  • 14. Code First approach - How to build Introspection query Introspection response Replace Relay definitions @MarcinStachniuk Typescript relay plugin GraphQL in Java
  • 15. GraphQL Java implementations How to implement GraphQL in Java? @MarcinStachniuk /graphql-java/graphql-java Schema First GraphQL in Java
  • 16. 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 in Java
  • 17. Schema First approach in comparison to Code First 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 in Java
  • 18. Schema First approach - How to build model.graphqls @MarcinStachniukGraphQL in Java
  • 19. GraphQL SPQR @MarcinStachniuk /leangen/graphql-spqr Senātus Populusque Rōmānus The Roman Senate and People pronounced like speaker GraphQL in Java
  • 20. SPQR approach public class UserService { @GraphQLQuery(name = "user") public User getById(@GraphQLArgument(name = "id") Integer id) { //... } } @MarcinStachniuk type Query { user(id: Int): User } GraphQL in Java By default argument names will be arg0, arg1,... You can use @GraphQLArgument or Compile code with -parameters option
  • 21. SPQR approach public class User { //... @GraphQLQuery(name = "name", description = "A person's name") public String getName() { return name; } } @MarcinStachniuk type User { # A person's name name: String } GraphQL in Java
  • 22. 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; } } @MarcinStachniuk // 'ID' type in schema, add 'implements Node' // add ! (non null) in schema // optional // add ! (non null) because it’s int GraphQL in Java
  • 23. Classic Code First Approach Pros: ● Stable library ● Some Javadoc and documentation ● It was the only way at the beginning to define a schema @MarcinStachniuk 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 GraphQL in Java
  • 24. Schema First Approach Pros: ● Easy to maintain and understand ● Stable library ● Some Javadoc and documentation ● DSL defined in specification ● Reduce boilerplate to write ● A possibility to split schema into more files ● Parallel development (frontend & backend) @MarcinStachniuk 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 GraphQL in Java
  • 25. SPQR Approach Pros: ● The author reply to Github issues quickly ● Reduce boilerplate to write ● No mismatch between Schema and Java code ● No binding between schema and DataFetchers is needed ● Many “DataFetchers” in single class ● Smart Relay conventions @MarcinStachniuk Cons: ● 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 GraphQL in Java
  • 26. What to choose? Classic Code First Approach is the worst @MarcinStachniuk ● Big project ● High risk project ● Old project ● Small project ● Low risk project ● New Project ? GraphQL in Java
  • 27. Prisma version? @MarcinStachniukGraphQL in Java https://www.prisma.io/blog/the-problems-of-schema-first-graphql-developm ent-x1mn4cb0tyl3
  • 28. Alternatives out of scope this presentation @MarcinStachniukGraphQL in Java ● GraphQL Java Tools https://github.com/graphql-java-kickstart/graphql-java-tools ● graphql-spring-boot-starter https://github.com/graphql-java-kickstart/graphql-spring-boot ● Micronaut GraphQL https://github.com/micronaut-projects/micronaut-graphql ● graphql-kotlin https://github.com/ExpediaGroup/graphql-kotlin ● KGraphQL https://github.com/aPureBase/KGraphQL ● Sangria https://sangria-graphql.org/ ● Lacinia https://github.com/walmartlabs/lacinia ● Gorm GraphQL https://github.com/grails/gorm-graphql/ ● GQL https://grooviter.github.io/gql/
  • 30. Testing GraphQL @SpringBootTest @ContextConfiguration(classes = Main) class CustomerFetcherSpec extends Specification { @Autowired GraphQLSchema graphQLSchema GraphQL graphQL def setup() { graphQL = GraphQL.newGraphQL(graphQLSchema).build() } @MarcinStachniukGraphQL in Java
  • 31. 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 in Java
  • 32. Versioning type Query { customer(id: String!): Customer! @deprecated(reason: "not used ...") @MarcinStachniukGraphQL in Java
  • 34. From Code First to Schema First migration https://github.com/mstachniuk/graphql-schema-from-introspection-generator @MarcinStachniukGraphQL in Java
  • 35. From Code First to Schema First migration alternatives ● In graphql-java - see: IntrospectionResultToSchema ● In graphql-js: const graphql = require("graphql"); const schema = require("path/to/schema.json"); const clientSchema = graphql.buildClientSchema(schema.data); const schemaString = graphql.printSchema(clientSchema); console.log(schemaString) @MarcinStachniukGraphQL in Java
  • 36. GraphQL downsides: N+1 problem { customers { 1 call id name orders { n calls id status } } } java-dataloader ● Add async BatchLoader ● Add caching @MarcinStachniuk graphQL = GraphQL.newGraphQL(schema) .queryExecutionStrategy( new BatchedExecutionStrategy()) .build(); + @Batched in DataFetcher#get() GraphQL in Java
  • 37. GraphQL downsides: N+1 problem If you have N + 1 problem use java-dataloader @MarcinStachniukGraphQL in Java
  • 38. Complex Queries fragment Friends on Friend { id name friends { id name friends { id name ... } } } @MarcinStachniuk graphQL = GraphQL.newGraphQL(schema) .instrumentation( new ChainedInstrumentation(asList( new MaxQueryComplexityInstrumentation(20), new MaxQueryDepthInstrumentation(2) ))) .build(); GraphQL in Java
  • 39. Complex Queries Performance killer? Define instrumentation! @MarcinStachniukGraphQL in Java
  • 42. Recommended tools: Altair GraphQL Client @MarcinStachniukGraphQL in Java https://altair.sirmuel.design/
  • 43. Recommended tools: Relay @MarcinStachniukGraphQL in Java @MarcinStachniuk user(...) { photo(width: "120", height: "120") } user(...) { name } user(...) { email } user(...) { name email photo(width: "120", height: "120") } GraphQL in Java
  • 44. Recommended tools: GraphQL schema linter https://github.com/cjoudrey/graphql-schema-linter Validate GraphQL schema definitions against a set of rules @MarcinStachniukGraphQL in Java
  • 45. Recommended tools: Graphql network - Chrome extension @MarcinStachniuk https://chrome.google.com/webstore/detail/graphql-network/ool bobjfnfdnpgjcaphejlodpbefhmbn GraphQL in Java
  • 46. Recommended tools: Graphql network - Chrome extension @MarcinStachniukGraphQL in Java
  • 47. More libraries and projects related to graphql-java https://github.com/graphql-java/awesome-graphql-java @MarcinStachniukGraphQL in Java
  • 48. Good practices ● Always generate GraphQL Schema and commit into your repository ● Follow conventions (e.g. Relay) ● Validate your schema ● Do not use classic code first approach to define schema @MarcinStachniukGraphQL in Java