package readme; import graphql.GraphQL; import graphql.Scalars; import graphql.StarWarsData; import graphql.StarWarsSchema; import graphql.TypeResolutionEnvironment; import graphql.execution.ExecutorServiceExecutionStrategy; import graphql.execution.SimpleExecutionStrategy; import graphql.language.Directive; import graphql.language.FieldDefinition; import graphql.language.InterfaceTypeDefinition; import graphql.language.TypeDefinition; import graphql.language.UnionTypeDefinition; import graphql.schema.Coercing; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import graphql.schema.GraphQLEnumType; import graphql.schema.GraphQLInputObjectType; import graphql.schema.GraphQLInterfaceType; import graphql.schema.GraphQLList; import graphql.schema.GraphQLNonNull; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLScalarType; import graphql.schema.GraphQLSchema; import graphql.schema.GraphQLTypeReference; import graphql.schema.GraphQLUnionType; import graphql.schema.StaticDataFetcher; import graphql.schema.TypeResolver; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; import graphql.schema.idl.SchemaParser; import graphql.schema.idl.TypeDefinitionRegistry; import graphql.schema.idl.WiringFactory; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import static graphql.GarfieldSchema.Cat; import static graphql.GarfieldSchema.CatType; import static graphql.GarfieldSchema.Dog; import static graphql.GarfieldSchema.DogType; import static graphql.MutationSchema.mutationType; import static graphql.Scalars.GraphQLBoolean; import static graphql.Scalars.GraphQLString; import static graphql.StarWarsSchema.queryType; import static graphql.schema.GraphQLArgument.newArgument; import static graphql.schema.GraphQLEnumType.newEnum; import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; import static graphql.schema.GraphQLInputObjectField.newInputObjectField; import static graphql.schema.GraphQLInputObjectType.newInputObject; import static graphql.schema.GraphQLInterfaceType.newInterface; import static graphql.schema.GraphQLList.list; import static graphql.schema.GraphQLNonNull.nonNull; import static graphql.schema.GraphQLObjectType.newObject; import static graphql.schema.GraphQLUnionType.newUnionType; import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring; /** * This class holds readme examples so they stay correct and can be compiled. If this * does not parse, chances are the readme examples are now wrong. * * You should place these examples into the README.next.md and NOT the main README.md. This allows * 'master' to progress yet shows consumers the released information about the project. */ @SuppressWarnings({"unused", "Convert2Lambda", "UnnecessaryLocalVariable", "ConstantConditions", "SameParameterValue"}) public class ReadmeExamples { public Map<String, Object> getInputFromJSON() { return new HashMap<>(); } class Foo { } void creatingASchema() { GraphQLSchema schema = GraphQLSchema.newSchema() .query(queryType) // must be provided .mutation(mutationType) // is optional .build(); } void listsAndNonNullLists() { GraphQLList.list(GraphQLString); // a list of Strings GraphQLNonNull.nonNull(GraphQLString); // a non null String // with static imports its even shorter newArgument() .name("example") .type(nonNull(list(GraphQLString))); } void newType() { GraphQLObjectType simpsonCharacter = newObject() .name("SimpsonCharacter") .description("A Simpson character") .field(newFieldDefinition() .name("name") .description("The name of the character.") .type(GraphQLString)) .field(newFieldDefinition() .name("mainCharacter") .description("One of the main Simpson characters?") .type(GraphQLBoolean)) .build(); } void interfaceType() { GraphQLInterfaceType comicCharacter = newInterface() .name("ComicCharacter") .description("A abstract comic character.") .field(newFieldDefinition() .name("name") .description("The name of the character.") .type(GraphQLString)) .build(); } void inputTypes() { GraphQLInputObjectType inputObjectType = newInputObject() .name("inputObjectType") .field(newInputObjectField() .name("field") .type(GraphQLString)) .build(); } void enumTypes() { GraphQLEnumType colorEnum = newEnum() .name("Color") .description("Supported colors.") .value("RED") .value("GREEN") .value("BLUE") .build(); } void unionType() { GraphQLUnionType PetType = newUnionType() .name("Pet") .possibleType(CatType) .possibleType(DogType) .typeResolver(new TypeResolver() { @Override public GraphQLObjectType getType(TypeResolutionEnvironment env) { if (env.getObject() instanceof Cat) { return CatType; } if (env.getObject() instanceof Dog) { return DogType; } return null; } }) .build(); } void recursiveTypes() { GraphQLObjectType person = newObject() .name("Person") .field(newFieldDefinition() .name("friends") .type(new GraphQLList(new GraphQLTypeReference("Person")))) .build(); } void executionStrategies() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, /* core pool size 2 thread */ 2, /* max pool size 2 thread */ 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy()); GraphQL graphQL = GraphQL.newGraphQL(StarWarsSchema.starWarsSchema) .queryExecutionStrategy(new ExecutorServiceExecutionStrategy(threadPoolExecutor)) .mutationExecutionStrategy(new SimpleExecutionStrategy()) .subscriptionExecutionStrategy(new SimpleExecutionStrategy()) .build(); } void dataFetching() { DataFetcher<Foo> fooDataFetcher = new DataFetcher<Foo>() { @Override public Foo get(DataFetchingEnvironment environment) { // environment.getSource() is the value of the surrounding // object. In this case described by objectType Foo value = perhapsFromDatabase(); // Perhaps getting from a DB or whatever return value; } }; GraphQLObjectType objectType = newObject() .name("ObjectType") .field(newFieldDefinition() .name("foo") .type(GraphQLString) .dataFetcher(fooDataFetcher)) .build(); } class Review { } class Episode { } class ReviewInput { } class ReviewStore { Review update(Episode episode, ReviewInput reviewInput) { return null; } } private ReviewStore reviewStore() { return new ReviewStore(); } void mutationExample() { GraphQLInputObjectType episodeType = GraphQLInputObjectType.newInputObject() .name("Episode") .field(newInputObjectField() .name("episodeNumber") .type(Scalars.GraphQLInt)) .build(); GraphQLInputObjectType reviewInputType = GraphQLInputObjectType.newInputObject() .name("ReviewInput") .field(newInputObjectField() .name("stars") .type(Scalars.GraphQLString) .name("commentary") .type(Scalars.GraphQLString)) .build(); GraphQLObjectType reviewType = newObject() .name("Review") .field(newFieldDefinition() .name("stars") .type(GraphQLString)) .field(newFieldDefinition() .name("commentary") .type(GraphQLString)) .build(); GraphQLObjectType createReviewForEpisodeMutation = newObject() .name("CreateReviewForEpisodeMutation") .field(newFieldDefinition() .name("createReview") .type(reviewType) .argument(newArgument() .name("episode") .type(episodeType) ) .argument(newArgument() .name("review") .type(reviewInputType) ) .dataFetcher(mutationDataFetcher()) ) .build(); GraphQLSchema schema = GraphQLSchema.newSchema() .query(queryType) .mutation(createReviewForEpisodeMutation) .build(); } private DataFetcher mutationDataFetcher() { return new DataFetcher() { @Override public Review get(DataFetchingEnvironment environment) { Episode episode = environment.getArgument("episode"); ReviewInput review = environment.getArgument("review"); // make a call to your store to mutate your database Review updatedReview = reviewStore().update(episode, review); // this returns a new view of the data return updatedReview; } }; } private Object context() { return null; } private Foo perhapsFromDatabase() { return new Foo(); } void parsedSchemaExample() { SchemaParser schemaParser = new SchemaParser(); SchemaGenerator schemaGenerator = new SchemaGenerator(); File schemaFile = loadSchema("starWarsSchema.graphqls"); TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFile); RuntimeWiring wiring = buildRuntimeWiring(); GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, wiring); } void parsedSplitSchemaExample() { SchemaParser schemaParser = new SchemaParser(); SchemaGenerator schemaGenerator = new SchemaGenerator(); File schemaFile1 = loadSchema("starWarsSchemaPart1.graphqls"); File schemaFile2 = loadSchema("starWarsSchemaPart2.graphqls"); File schemaFile3 = loadSchema("starWarsSchemaPart3.graphqls"); TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry(); // each compiled registry is merged into the main registry typeRegistry.merge(schemaParser.parse(schemaFile1)); typeRegistry.merge(schemaParser.parse(schemaFile2)); typeRegistry.merge(schemaParser.parse(schemaFile3)); GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, buildRuntimeWiring()); } RuntimeWiring buildRuntimeWiring() { return RuntimeWiring.newRuntimeWiring() .scalar(CustomScalar) // this uses builder function lambda syntax .type("QueryType", typeWiring -> typeWiring .dataFetcher("hero", new StaticDataFetcher(StarWarsData.getArtoo())) .dataFetcher("human", StarWarsData.getHumanDataFetcher()) .dataFetcher("droid", StarWarsData.getDroidDataFetcher()) ) .type("Human", typeWiring -> typeWiring .dataFetcher("friends", StarWarsData.getFriendsDataFetcher()) ) // you can use builder syntax if you don't like the lambda syntax .type(newTypeWiring("Droid") .dataFetcher("friends", StarWarsData.getFriendsDataFetcher()) ) // or full builder syntax if that takes your fancy where you call .build() .type( newTypeWiring("Character") .typeResolver(StarWarsData.getCharacterTypeResolver()) .build() ) .build(); } RuntimeWiring buildDynamicRuntimeWiring() { WiringFactory dynamicWiringFactory = new WiringFactory() { @Override public boolean providesTypeResolver(TypeDefinitionRegistry registry, InterfaceTypeDefinition definition) { return getDirective(definition,"specialMarker") != null; } @Override public boolean providesTypeResolver(TypeDefinitionRegistry registry, UnionTypeDefinition definition) { return getDirective(definition, "specialMarker") != null; } @Override public TypeResolver getTypeResolver(TypeDefinitionRegistry registry, InterfaceTypeDefinition definition) { Directive directive = getDirective(definition, "specialMarker"); return createTypeResolver(definition, directive); } @Override public TypeResolver getTypeResolver(TypeDefinitionRegistry registry, UnionTypeDefinition definition) { Directive directive = getDirective(definition,"specialMarker"); return createTypeResolver(definition,directive); } @Override public boolean providesDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) { return getDirective(definition,"dataFetcher") != null; } @Override public DataFetcher getDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) { Directive directive = getDirective(definition, "dataFetcher"); return createDataFetcher(definition,directive); } }; return RuntimeWiring.newRuntimeWiring() .wiringFactory(dynamicWiringFactory).build(); } private DataFetcher createDataFetcher(FieldDefinition definition, Directive directive) { throw new UnsupportedOperationException("Not implemented"); } private TypeResolver createTypeResolver(TypeDefinition definition, Directive directive) { throw new UnsupportedOperationException("Not implemented"); } private Directive getDirective(TypeDefinition definition, String type) { throw new UnsupportedOperationException("Not implemented"); } private Directive getDirective(FieldDefinition fieldDefintion, String type) { throw new UnsupportedOperationException("Not implemented"); } public static GraphQLScalarType CustomScalar = new GraphQLScalarType("Custom", "Custom Scalar", new Coercing<Integer, Integer>() { @Override public Integer serialize(Object input) { throw new UnsupportedOperationException("Not implemented"); } @Override public Integer parseValue(Object input) { throw new UnsupportedOperationException("Not implemented"); } @Override public Integer parseLiteral(Object input) { throw new UnsupportedOperationException("Not implemented"); } }); private File loadSchema(String s) { return null; } }