Oliver Zeigermann / @DJCordhose
Folien: https://djcordhose.github.io/graphql-sandbox/talk/2017_graphql_jax.html
Beispiel: Issues heraussuchen
query {
repositoryOwner(login: "DJCordhose") {
repository(name: "architecture") {
id
issues(first: 10) {
edges {
node {
id
title
}
}
}
}
}
}
Die ersten 10 Issues des Repositories architecture
Ergebnis
{ "data": {
"repositoryOwner": {
"repository": {
"id": "MDEwOlJlcG9zaXRvcnk2MDE1NTgyMA==",
"issues": {
"edges": [
{
"node": {
"id": "MDU6SXNzdWUxNzk0ODczMTg=",
"title": "TestIssue"
}
}
]
}
}
}
}
}
Die ersten 10 Issues des Repositories architecture
Beispiel: Einem Issue einen Kommentar hinzufügen
mutation {
addComment(input:{
subjectId: "MDU6SXNzdWUxNzk0ODczMTg=",
clientMutationId: "Sandbox",
body: "Comment from JAX 2017"
}) {
clientMutationId
}
}
Ergebnis der Ausführung auf GitHub
query {
customer (id: "c1") {
lastname, adress { email }
}
}
Operations
Beschreibt die API (Objekte und Operations)
Server zum Ausführen von GraphQL Anfragen
(Spezifikation noch in Arbeit!)
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ hello }"}' \
http://localhost:8080
Antwort:
{"data":{"hello":"Hello world!"}}
public class Customer {
@GraphQLField
@GraphQLNonNull
private String id;
@GraphQLField
private String lastName;
@GraphQLField
private Address address;
@GraphQLField
private List<Phone> phones;
}
enum PhoneType { BUSINESS, PRIVATE }
public class Customer {
private List<Phone> phones;
@GraphQLField
public List<Phone> phonesWithType(
@GraphQLName("type") PhoneType type) {
return phones.stream()
.filter(phone -> phone.getPhoneType() == type)
.collect(Collectors.toList());
}
}
import graphql.servlet.SimpleGraphQLServlet;
public class CustomerGraphQLServlet extends SimpleGraphQLServlet {
public CustomerGraphQLServlet() {
super(CustomerSchema.createCustomerQuerySchema(), null);
}
}
import graphql.annotations.GraphQLAnnotations;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
public class CustomerSchema {
public static GraphQLSchema createCustomerQuerySchema() {
// Define the Customer-Type based on Annotations
final GraphQLObjectType customerType =
GraphQLAnnotations.object(Customer.class);
GraphQLSchema schema = GraphQLSchema.newSchema()
// Add the "Query" type to Schema (required)
.query(buildCustomerQueryType(customerType))
// Add the "Mutation" type to Schema (optional)
.mutation(buildCustomerMutationType(customerType))
.build();
return schema;
}
}
GraphQLObjectType buildQueryType(GraphQLObjectType customerType) {
return newObject()
.field(newFieldDefinition()
// set the name
.name("customer")
// declare return type of the query
.type(customerType)
// define args for the query
.argument(new GraphQLArgument("id",
new GraphQLNonNull(GraphQLID)))
// implement fetch logic
.dataFetcher(environment -> {
final String id = environment.getArgument("id");
return customerService.findCustomerById(id);
}).build())
.build();
}
Analog zum Query
Im DataFetcher wird Logik zum Speichern implementiert
GraphQLObjectType buildMutationType(GraphQLObjectType customerType) {
return newObject()
.field(newFieldDefinition()
.name("addCustomer")
.type(customerType)
.argument(. . .)
.dataFetcher(environment -> {
final String lastName = environment.getArgument("lastName");
final String email = environment.getArgument("email");
final Customer newCustomer = customerService
.newCustomer(lastName, email);
return newCustomer;
}).build())
.build();
}
type Customer {
# Mandatory field (note the !)
id: ID!
firstName: String
address: Address
# List of Phones
phones: [Phone]
# Field with (mandatory) argument
phonesWithType(type: PhoneType!): [Phone]
}
# Enum Value
enum PhoneType { PRIVATE, BUSINESS }
type Phone { type: PhoneType!, number: String! }
Queries und Mutations
type Query {
hello: String
}
type Query {
customer(id: ID): Customer
}
type Mutation {
addCustomer(lastName: String, email: String!): Customer!
}
const { buildSchema } = require('graphql');
const customerSchema = buildSchema(`
type Customer { . . . }
type Query {
hello: String!
customer(id: ID!): Customer
}
type Mutation {
addCustomer(lastName: String, email: String!): Customer!
}
`);
const root = {
// Query Implementations
hello: () => "Hello, World",
customer: ({id}) => CUSTOMERS.find(p => p.id === id),
// Mutation
addCustomer: ({lastName, email}) => CUSTOMERS.push(...)
};
const graphqlHTTP = require('express-graphql');
app.use('/graphql', graphqlHTTP({
schema: customerSchema,
rootValue: root,
// enable GraphiQL Browser
graphiql: true
}));
class Customer {
constructor(id, firstName, lastName, address, phones) {
this.firstName = firstName;
// more assignments. . .
}
phonesWithType({ type }) {
return this.phones.filter
(phone => phone.phoneType === type);
}
}