Skip to content

Commit 1ab7123

Browse files
authored
Merge pull request #113 from Jahia/type-extensions
Type extensions
2 parents 9a600e1 + 07c529f commit 1ab7123

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,88 @@ field.
113113

114114
You can specify a custom data fetcher for a field with `@GraphQLDataFetcher`
115115

116+
## Type extensions
117+
118+
Having one single class declaring all fields in a graphQL object type is not always possible, or can lead to huge classes.
119+
Modularizing the schema by defining fields in different classes allows you to split it in smaller chunks of codes.
120+
In IDL, this is usually written by using the `extend` keyword on top of a type definition. So you have a type defined like this :
121+
122+
```
123+
type Human {
124+
id: ID!
125+
name: String!
126+
}
127+
```
128+
129+
It would be possible to extend it later on by using the following syntax :
130+
131+
```
132+
extend type Human {
133+
homePlanet: String
134+
}
135+
```
136+
137+
### Defining extensions in annotations
138+
139+
This is possible when using annotations by registering "extensions" classes, corresponding to `extend` clauses, before creating the objects with the GraphQLAnnotationsProcessor.
140+
Extension classes are simple classes, using the same annotations, with an additional `@GraphQLTypeExtension` on the class itself. The annotation value is required and will be the class that it actually extends.
141+
142+
So the previous schema could be defined by the following classes :
143+
144+
```
145+
@GraphQLName("Human")
146+
public class Human {
147+
@GraphQLField
148+
public String name() { }
149+
}
150+
```
151+
152+
```
153+
@GraphQLTypeExtension(Human.class)
154+
public class HumanExtension {
155+
@GraphQLField
156+
public String homePlanet() { }
157+
}
158+
```
159+
160+
Classes marked as "extensions" will actually not define a new type, but rather set new fields on the class it extends when it will be created.
161+
All GraphQL annotations can be used on extension classes.
162+
163+
Extensions are registered in GraqhQLAnnotationProcessor by using `registerTypeExtension`. Note that extensions must be registered before the type itself is requested with `getObject()` :
164+
165+
```
166+
GraphQLAnnotationsProcessor processor = GraphQLAnnotations.getInstance();
167+
168+
// Register extensions
169+
processor.registerTypeExtension(HumanExtension.class);
170+
171+
// Create type
172+
GraphQLObjectType type = processor.getObject(Human.class);
173+
174+
```
175+
176+
### Data fetching with extensions
177+
178+
As opposed to standard annotated classes mapped to GraphQL types, no instance of the extensions are created by default.
179+
In DataFetcher, the source object will still be an instance of the extended class.
180+
It is however possible to provide a constructor taking the extended class as parameter. This constructor will be used to create an instance of the extension class when a field with the default DataFetcher (without `@DataFetcher`) will be queried.
181+
If no such constructor is provided, the field must either be declared as `static` or marked as `@GraphQLInvokeDetached`. Original source object can be found in the `DataFetchingEnvironment`.
182+
183+
```
184+
@GraphQLTypeExtension(Human.class)
185+
public class HumanExtension {
186+
187+
public HumanExtension(Human human) {
188+
this.human = human;
189+
}
190+
191+
@GraphQLField
192+
public String homePlanet() {
193+
// get value somehow from human object
194+
}
195+
}
196+
```
197+
116198
## Type Inference
117199

118200
By default, standard GraphQL types (String, Integer, Long, Float, Boolean, Enum, List) will be inferred from Java types. Also, it will respect `@javax.validation.constraints.NotNull` annotation with respect to value's nullability, as well as `@GraphQLNonNull`

src/main/java/graphql/annotations/GraphQLAnnotationsProcessor.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,20 @@ public interface GraphQLAnnotationsProcessor {
102102
* @return a {@link GraphQLInputObjectType}
103103
*/
104104
GraphQLInputObjectType getInputObject(GraphQLObjectType graphQLType, String newNamePrefix);
105+
106+
/**
107+
* Register a new type extension class. This extension will be used when the extended object will be created.
108+
* The class must have a {@link GraphQLTypeExtension} annotation.
109+
*
110+
* @param objectClass The extension class to register
111+
*/
112+
void registerTypeExtension(Class<?> objectClass);
113+
114+
/**
115+
* Unregister a type extension class.
116+
*
117+
* @param objectClass The extension class to unregister
118+
*/
119+
void unregisterTypeExtension(Class<?> objectClass);
120+
105121
}

0 commit comments

Comments
 (0)