
# GraphQL-Java Annotations

[]()
[GraphQL-Java](https://github.com/graphql-java/graphql-java) is a great library, but its syntax is a little bit verbose. This library offers an annotations-based syntax for GraphQL schema definition.
If you would like to use a tool that creates a graphql spring boot server using graphql-java-annotations, you can view the [graphql-spring-annotations](https://github.com/yarinvak/graphql-spring-annotations) library.
## Table Of Contents
- [Getting Started](#getting-started)
- [GraphQLAnnotations class](#graphqlannotations-class)
- [Annotations Schema Creator](#annotations-schema-creator)
- [Defining Objects](#defining-objects)
- [Defining Interfaces](#defining-interfaces)
- [Defining Unions](#defining-unions)
- [Fields](#fields)
- [Custom DataFetcher](#custom-data-fetcher)
- [Type Extensions](#type-extensions)
- [Defining Extensions in Annotation](#defining-extensions-in-annotations)
- [Data Fetching with Extensions](#data-fetching-with-extensions)
- [Type Inference](#type-inference)
- [Directives](#directives)
- [Creating/Defining a GraphQL Directive](#creatingdefining-a-graphqldirective)
- [Wiring with Directives](#wiring-with-directives)
- [Relay Support](#relay-support)
- [Mutations](#mutations)
- [Connection](#connection)
- [Customizing Relay Schema](#customizing-relay-schema)
- [Community and Governance](#community-and-governance)
## Getting Started
(Gradle syntax)
```groovy
dependencies {
compile "io.github.graphql-java:graphql-java-annotations:24.3"
}
```
(Maven syntax)
```groovy
io.github.graphql-javagraphql-java-annotations24.3
```
The graphql-java-annotations library is able to create GraphQLType objects out of your Java classes.
These GraphQLType objects can be later injected into the graphql-java schema.
graphql-java-annotations also allows you to wire your objects with data fetchers and type resolvers while annotating your fields/types. The result of this process will be a ``GraphQLCodeRegistry.Builder`` object that can be later built and injected to the graphql-java schema.
## GraphQLAnnotations class
You can create an instance of the `GraphQLAnnotations` class in order to create the GraphQL types.
```java
GraphQLAnnotations graphqlAnnotations = new GraphQLAnnotations();
```
Using this object, you will be able to create the GraphQL types.
There are few types that can be generated - a `GraphQLObjectType`, a `GraphQLInterfaceType` and a `GraphQLDirective`.
```java
GraphQLObjectType query = graphqlAnnotations.object(Query.class);
GraphQLDirective upperDirective = graphqlAnnotations.directive(UpperDirective.class);
GraphQLInterfaceType myInterface = graphqlAnnotations.generateInterface(MyInterface.class);
```
Then you can use these types in order to create a graphql-java schema.
But, in order to create a graphql-java schema, you need also the ``GraphQLCodeRegistry``, which contains all the data fetchers mapped to their fields (and also type resolvers).
You can obtain the code registry this way:
```java
graphqlAnnotations.getContainer().getCodeRegistryBuilder().build();
```
## Annotations Schema Creator
Using the `GraphQLAnnotations` processor object can be a little bit confusing if you wish to use it to create a GraphQL schema.
So we created a util class to help you create your desired GraphQL schema, in a syntax similiar to the graphql-java syntax.
In order to do so you can use the ``AnnotationsSchemaCreator.Builder`` in the following way:
```java
GraphQLSchema schema = AnnotationsSchemaCreator.newAnnotationsSchema()
.query(Query.class) // to create you query object
.mutation(Mutation.class) // to create your mutation object
.subscription(Subscription.class) // to create your subscription object
.directive(UpperDirective.class) // to create a directive
.additionalType(AdditionalType.class) // to create some additional type and add it to the schema
.typeFunction(CustomType.class) // to add a typefunction
.setAlwaysPrettify(true) // to set the global prettifier of field names (removes get/set/is prefixes from names)
.setRelay(customRelay) // to add a custom relay object
.build();
```
Of course you can use this builder with only some of the properties, but the query class must be provided.
note - The GraphQLSchema is a graphql-java type.
Continue reading in order to understand how your java classes should look in order to be provided to the annotations schema creator.
## Defining Objects
Any regular Java class can be converted to a GraphQL object type. Fields can
be defined with a `@GraphQLField` (see more on fields below) annotation:
```java
public class SomeObject {
@GraphQLField
public String field;
}
// ...
GraphQLAnnotations graphQLAnnotations = new GraphQLAnnotations();
GraphQLObjectType object = graphQLAnnotations.object(SomeObject.class);
```
## Defining Interfaces
This is very similar to defining objects, with the addition of type resolver :
```java
@GraphQLTypeResolver(MyTypeResolver.class)
public interface SomeInterface {
@GraphQLField
String field();
}
public class MyTypeResolver implements TypeResolver {
GraphQLObjectType getType(TypeResolutionEnvironment env) { ... }
}
// ...
GraphQLAnnotations graphQLAnnotations = new GraphQLAnnotations();
GraphQLInterfaceType object = graphQLAnnotations.generateInterface(SomeInterface.class);
```
An instance of the type resolver will be created from the specified class. If a `getInstance` method is present on the
class, it will be used instead of the default constructor.
## Defining Unions
To have a union, you must annotate an interface with `@GraphQLUnion`. In the annotation, you must declare all the
possible types of the union, and a type resolver.
If no type resolver is specified, `UnionTypeResolver` is used. It follows this algorithm:
The resolver assumes the the DB entity's name is the same as the API entity's name.
If so, it takes the result from the dataFetcher and decides to which
API entity it should be mapped (according to the name).
Example: If you have a `Pet` union type, and the dataFetcher returns `Dog`, the typeResolver
will check for each API entity if its name is equal to `Dog`, and returns if it finds something
```java
@GraphQLUnion(possibleTypes={Dog.class, Cat.class})
public interface Pet {}
```
and an example with custom `TypeResovler`:
```java
@GraphQLUnion(possibleTypes={DogApi.class, Cat.class}, typeResolver = PetTypeResolver.class)
public interface Pet {}
public class PetTypeResolver implements TypeResolver {
@Override
GraphQLObjectType getType(TypeResolutionEnvironment env) {
Object obj = env.getObject();
if(obj instanceof DogDB) {
return (GraphQLObjectType) env.getSchema().getType("DogApi");
}
else {
return (GraphQLObjectType) env.getSchema().getType("Cat");
}
}
}
```
NOTE: you can have (but not mandatory) a type resolver with constructor that has `Class>[]` as the first parameter and
`ProcessingElementsContainer` as the second. the `Class>[]` parameter contains the possibleTypes class
and `ProcessingElementsContainer` has all sorts of utils (you can check `UnionTypeResolver` to see how we use it there)
## Fields
In addition to specifying a field over a Java class field, a field can be defined over a method:
```java
public class SomeObject {
@GraphQLField
public String field() {
return "field";
}
}
```
Or a method with arguments:
```java
public class SomeObject {
@GraphQLField
public String field(String value) {
return value;
}
}
```
> Note: You need to use `-parameters` javac option to compile, which makes argument name as the default GraphQL name. Otherwise, you will need to add the `@GraphQLName("value")` annotation to specify one.
You can also inject `DataFetchingEnvironment` as an argument, at any position:
```java
public class SomeObject {
@GraphQLField
public String field(DataFetchingEnvironment env, String value) {
return value;
}
}
```
Additionally, `@GraphQLName` can be used to override field name. You can use `@GraphQLDescription` to set a description.
These can also be used for field parameters:
```java
public String field(@GraphQLName("val") String value) {
return value;
}
```
In addition, `@GraphQLDefaultValue` can be used to set a default value to a parameter. Due to limitations of annotations, the default value has to be provided by a class that implements `Supplier