Skip to content

Commit cce4c92

Browse files
committed
Merge branch 'up-master'
2 parents 547ffaf + e120188 commit cce4c92

File tree

15 files changed

+335
-19
lines changed

15 files changed

+335
-19
lines changed

README.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Build Status](https://travis-ci.org/graphql-java/graphql-java-annotations.svg?branch=master)](https://travis-ci.org/yrashk/graphql-java-annotations)
1+
[![Build Status](https://travis-ci.org/graphql-java/graphql-java-annotations.svg?branch=master)](https://travis-ci.org/graphql-java/graphql-java-annotations)
22
[![Maven Central](https://img.shields.io/maven-central/v/io.github.graphql-java/graphql-java-annotations.svg?maxAge=2592000)]()
33
# GraphQL Annotations for Java
44

@@ -12,7 +12,7 @@ syntax for GraphQL schema definition.
1212

1313
```groovy
1414
dependencies {
15-
compile "io.github.graphql-java:graphql-java-annotations:5.0.7"
15+
compile "io.github.graphql-java:graphql-java-annotations:5.2"
1616
}
1717
```
1818

@@ -34,18 +34,26 @@ GraphQLObjectType object = GraphQLAnnotations.object(SomeObject.class);
3434

3535
## Defining Interfaces
3636

37-
This is very similar to defining objects:
37+
This is very similar to defining objects, with the addition of type resolver :
3838

3939
```java
40+
@GraphQLTypeResolver(MyTypeResolver.class)
4041
public interface SomeInterface {
4142
@GraphQLField
4243
String field();
4344
}
4445

46+
public class MyTypeResolver implements TypeResolver {
47+
GraphQLObjectType getType(TypeResolutionEnvironment env) { ... }
48+
}
49+
4550
// ...
4651
GraphQLInterfaceType object = GraphQLAnnotations.iface(SomeInterface.class);
4752
```
4853

54+
An instance of the type resolver will be created from the specified class. If a `getInstance` method is present on the
55+
class, it will be used instead of the default constructor.
56+
4957
## Fields
5058

5159
In addition to specifying a field over a Java class field, a field can be defined over a method:
@@ -108,10 +116,21 @@ public String field(@GraphQLDefaultValue(DefaultValue.class) String value) {
108116
}
109117
```
110118

119+
The `DefaultValue` class can define a `getInstance` method that will be called instead of the default constructor.
120+
111121
`@GraphQLDeprecate` and Java's `@Deprecated` can be used to specify a deprecated
112122
field.
113123

114-
You can specify a custom data fetcher for a field with `@GraphQLDataFetcher`
124+
### Custom data fetcher
125+
126+
You can specify a custom data fetcher for a field with `@GraphQLDataFetcher`. The annotation will reference a class name,
127+
which will be used as data fetcher.
128+
129+
An instance of the data fetcher will be created. The `args` attribute on the annotation can be used to specify a list of
130+
String arguments to pass to the construcor, allowing to reuse the same class on different fields, with different parameter.
131+
The `firstArgIsTargetName` attribute can also be set on `@GraphQLDataFetcher` to pass the field name as a single parameter of the constructor.
132+
133+
If no argument is needed and a `getInstance` method is present, this method will be called instead of the constructor.
115134

116135
## Type extensions
117136

build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ repositories {
8282

8383
gradle.projectsEvaluated {
8484
tasks.withType(JavaCompile) {
85-
options.compilerArgs << "-parameters"
85+
doLast {
86+
options.compilerArgs += "-parameters"
87+
}
8688
}
8789
}
8890

src/main/java/graphql/annotations/GraphQLFieldDefinitionWrapper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
*/
1515
package graphql.annotations;
1616

17+
import graphql.schema.DataFetcher;
18+
import graphql.schema.DataFetcherFactories;
1719
import graphql.schema.GraphQLFieldDefinition;
1820

1921
public class GraphQLFieldDefinitionWrapper extends GraphQLFieldDefinition {
2022

2123
public GraphQLFieldDefinitionWrapper(GraphQLFieldDefinition fieldDefinition) {
2224
super(fieldDefinition.getName(), fieldDefinition.getDescription(), fieldDefinition.getType(),
23-
fieldDefinition.getDataFetcher(), fieldDefinition.getArguments(), fieldDefinition.getDeprecationReason());
25+
DataFetcherFactories.useDataFetcher((DataFetcher<?>)fieldDefinition.getDataFetcher()), fieldDefinition.getArguments(), fieldDefinition.getDeprecationReason(),
26+
fieldDefinition.getDefinition());
2427
}
2528

2629
@Override

src/main/java/graphql/annotations/connection/GraphQLConnection.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,11 @@
5252
* @return a connection validator
5353
*/
5454
Class <? extends ConnectionValidator> validator() default PaginatedDataConnectionTypeValidator.class;
55+
56+
/**
57+
* By default, the paginated data is fetched synchronously. If explicitly specified, asynchronous data fetching
58+
* will be used.
59+
* @return if async fetching to be used.
60+
*/
61+
boolean async() default false;
5562
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright 2016 Yurii Rashkovskii
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
*/
15+
package graphql.annotations.dataFetchers.connection;
16+
17+
import graphql.schema.DataFetcher;
18+
import graphql.schema.DataFetchingEnvironment;
19+
20+
import java.util.concurrent.CompletableFuture;
21+
22+
import static java.util.concurrent.CompletableFuture.supplyAsync;
23+
24+
public class AsyncConnectionDataFetcher<T> implements DataFetcher<CompletableFuture<graphql.relay.Connection<T>>> {
25+
private final ConnectionDataFetcher connectionDataFetcher;
26+
27+
@SuppressWarnings("unchecked")
28+
public AsyncConnectionDataFetcher(ConnectionDataFetcher connectionFetcher) {
29+
this.connectionDataFetcher = connectionFetcher;
30+
}
31+
32+
@Override
33+
public CompletableFuture<graphql.relay.Connection<T>> get(DataFetchingEnvironment environment) {
34+
return supplyAsync(() -> connectionDataFetcher.get(environment));
35+
}
36+
}

src/main/java/graphql/annotations/processor/retrievers/fieldBuilders/field/FieldDataFetcherBuilder.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
import graphql.annotations.connection.GraphQLConnection;
2020
import graphql.annotations.dataFetchers.ExtensionDataFetcherWrapper;
2121
import graphql.annotations.dataFetchers.MethodDataFetcher;
22-
import graphql.annotations.dataFetchers.connection.ConnectionDataFetcher;
2322
import graphql.annotations.processor.ProcessingElementsContainer;
2423
import graphql.annotations.processor.retrievers.fieldBuilders.Builder;
2524
import graphql.annotations.processor.typeFunctions.TypeFunction;
2625
import graphql.annotations.processor.util.DataFetcherConstructor;
27-
import graphql.schema.*;
26+
import graphql.schema.DataFetcher;
27+
import graphql.schema.GraphQLNonNull;
28+
import graphql.schema.GraphQLType;
29+
import graphql.schema.PropertyDataFetcher;
2830

2931
import java.lang.reflect.Field;
3032
import java.lang.reflect.Method;
3133

3234
import static graphql.Scalars.GraphQLBoolean;
35+
import static graphql.annotations.processor.util.ConnectionUtil.getConnectionDataFetcher;
3336
import static java.util.Objects.nonNull;
3437

3538
public class FieldDataFetcherBuilder implements Builder<DataFetcher> {
@@ -61,9 +64,8 @@ public DataFetcher build() {
6164
actualDataFetcher = handleNullCase(actualDataFetcher);
6265
}
6366

64-
6567
if (isConnection) {
66-
actualDataFetcher = new ConnectionDataFetcher(field.getAnnotation(GraphQLConnection.class).connection(), actualDataFetcher);
68+
actualDataFetcher = getConnectionDataFetcher(field.getAnnotation(GraphQLConnection.class), actualDataFetcher);
6769
}
6870
return actualDataFetcher;
6971
}
@@ -75,7 +77,7 @@ private DataFetcher handleNullCase(DataFetcher actualDataFetcher) {
7577
actualDataFetcher = getBooleanDataFetcher(actualDataFetcher);
7678
} else if (checkIfPrefixGetterExists(field.getDeclaringClass(), "get", field.getName())) {
7779
actualDataFetcher = wrapExtension(new PropertyDataFetcher(field.getName()), field);
78-
} else{
80+
} else {
7981
actualDataFetcher = getDataFetcherWithFluentGetter(actualDataFetcher);
8082
}
8183

src/main/java/graphql/annotations/processor/retrievers/fieldBuilders/method/MethodDataFetcherBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import graphql.annotations.dataFetchers.BatchedMethodDataFetcher;
2222
import graphql.annotations.dataFetchers.MethodDataFetcher;
2323
import graphql.annotations.dataFetchers.RelayMutationMethodDataFetcher;
24-
import graphql.annotations.dataFetchers.connection.ConnectionDataFetcher;
2524
import graphql.annotations.processor.ProcessingElementsContainer;
2625
import graphql.annotations.processor.retrievers.fieldBuilders.Builder;
2726
import graphql.annotations.processor.typeFunctions.TypeFunction;
@@ -34,6 +33,8 @@
3433
import java.lang.reflect.Method;
3534
import java.util.List;
3635

36+
import static graphql.annotations.processor.util.ConnectionUtil.getConnectionDataFetcher;
37+
3738
public class MethodDataFetcherBuilder implements Builder<DataFetcher> {
3839
private Method method;
3940
private GraphQLOutputType outputType;
@@ -74,7 +75,7 @@ public DataFetcher build() {
7475
}
7576

7677
if (isConnection){
77-
actualDataFetcher = new ConnectionDataFetcher(method.getAnnotation(GraphQLConnection.class).connection(), actualDataFetcher);
78+
actualDataFetcher = getConnectionDataFetcher(method.getAnnotation(GraphQLConnection.class), actualDataFetcher);
7879
}
7980
return actualDataFetcher;
8081
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Copyright 2016 Yurii Rashkovskii
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
*/
15+
package graphql.annotations.processor.typeFunctions;
16+
17+
import graphql.annotations.processor.ProcessingElementsContainer;
18+
import graphql.schema.GraphQLList;
19+
import graphql.schema.GraphQLType;
20+
21+
import java.lang.reflect.AnnotatedArrayType;
22+
import java.lang.reflect.AnnotatedType;
23+
import java.lang.reflect.ParameterizedType;
24+
25+
public class ArrayFunction implements TypeFunction {
26+
27+
private DefaultTypeFunction defaultTypeFunction;
28+
29+
public ArrayFunction(DefaultTypeFunction defaultTypeFunction) {
30+
this.defaultTypeFunction = defaultTypeFunction;
31+
}
32+
33+
@Override
34+
public boolean canBuildType(Class<?> aClass, AnnotatedType annotatedType) {
35+
return aClass.isArray();
36+
}
37+
38+
@Override
39+
public GraphQLType buildType(boolean input, Class<?> aClass, AnnotatedType annotatedType, ProcessingElementsContainer container) {
40+
if (!(annotatedType instanceof AnnotatedArrayType)) {
41+
throw new IllegalArgumentException("Array type parameter should be specified");
42+
}
43+
AnnotatedArrayType parameterizedType = (AnnotatedArrayType) annotatedType;
44+
AnnotatedType arg = parameterizedType.getAnnotatedGenericComponentType();
45+
Class<?> klass;
46+
if (arg.getType() instanceof ParameterizedType) {
47+
klass = (Class<?>) ((ParameterizedType) (arg.getType())).getRawType();
48+
} else {
49+
klass = (Class<?>) arg.getType();
50+
}
51+
return new GraphQLList(defaultTypeFunction.buildType(input, klass, arg, container));
52+
}
53+
}

src/main/java/graphql/annotations/processor/typeFunctions/DefaultTypeFunction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public void activate() {
6262
typeFunctions.add(new BigDecimalFunction());
6363
typeFunctions.add(new CharFunction());
6464
typeFunctions.add(new IterableFunction(DefaultTypeFunction.this));
65+
typeFunctions.add(new ArrayFunction(DefaultTypeFunction.this));
6566
typeFunctions.add(new StreamFunction(DefaultTypeFunction.this));
6667
typeFunctions.add(new OptionalFunction(DefaultTypeFunction.this));
6768
typeFunctions.add(new ObjectFunction(graphQLInputProcessor, graphQLOutputProcessor));

src/main/java/graphql/annotations/processor/typeFunctions/IterableFunction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
/**
2626
* Support for the Iterable things like Lists / Sets / Collections and so on..
2727
*/
28-
class IterableFunction implements TypeFunction {
28+
class IterableFunction implements TypeFunction {
2929

3030
private DefaultTypeFunction defaultTypeFunction;
3131

32-
public IterableFunction(DefaultTypeFunction defaultTypeFunction){
33-
this.defaultTypeFunction=defaultTypeFunction;
32+
public IterableFunction(DefaultTypeFunction defaultTypeFunction) {
33+
this.defaultTypeFunction = defaultTypeFunction;
3434
}
3535

3636
@Override
@@ -51,6 +51,6 @@ public GraphQLType buildType(boolean input, Class<?> aClass, AnnotatedType annot
5151
} else {
5252
klass = (Class<?>) arg.getType();
5353
}
54-
return new GraphQLList(defaultTypeFunction.buildType(input, klass, arg,container));
54+
return new GraphQLList(defaultTypeFunction.buildType(input, klass, arg, container));
5555
}
56-
}
56+
}

0 commit comments

Comments
 (0)