diff --git a/content/tools/directives/index.md b/content/tools/directives/index.md
index 8d09a2d..ab5da66 100644
--- a/content/tools/directives/index.md
+++ b/content/tools/directives/index.md
@@ -68,9 +68,12 @@ Arguments the SDL leaves out are filled in with their default from the directive
An enum that's only used by directive definitions doesn't need a Java class. Its values are then passed to the wiring as `String`s. Add the enum to the [type dictionary]({{< relref "/tools/schema-definition/index.md#type-dictionary" >}}) to get the enum constants instead.
+Wirings run once the whole schema is built, like in graphql-java, so the types they see are the real ones and not `GraphQLTypeReference`s.
+
## Supported locations
-Support for directives is currently limited to the following locations:
+Wirings run for directives on the following locations:
+* `SCALAR`
* `OBJECT`
* `FIELD_DEFINITION`
* `ARGUMENT_DEFINITION`
@@ -81,8 +84,6 @@ Support for directives is currently limited to the following locations:
* `INPUT_OBJECT`
* `INPUT_FIELD_DEFINITION`
-Meaning directives for the following locations are currently not yet supported:
-
-* `SCALAR`
+A directive applied where its definition doesn't allow it, without a required argument, or more than once without being `repeatable` logs a warning. These will fail the build in 15.0.0.
Directives on `schema` and `extend schema` don't run a wiring, but they're added to the schema's applied directives. Like everywhere else, they have to be declared, unless `allowUndeclaredDirectives` is set in the [schema parser options]({{< relref "/tools/schema-parser-options/index.md" >}}).
diff --git a/content/tools/getting-started/index.md b/content/tools/getting-started/index.md
index 1962b3f..f80bba2 100644
--- a/content/tools/getting-started/index.md
+++ b/content/tools/getting-started/index.md
@@ -34,7 +34,7 @@ Add the `graphql-java-tools` dependency:
```gradle
dependencies {
- implementation 'io.github.graphql-java-kickstart:graphql-java-tools:14.3.0'
+ implementation 'io.github.graphql-java-kickstart:graphql-java-tools:14.4.0'
}
```
@@ -46,7 +46,7 @@ Add the `graphql-java-tools` dependency:
io.github.graphql-java-kickstart
graphql-java-tools
- 14.3.0
+ 14.4.0
```
diff --git a/content/tools/schema-definition/index.md b/content/tools/schema-definition/index.md
index fd99a46..bd10454 100644
--- a/content/tools/schema-definition/index.md
+++ b/content/tools/schema-definition/index.md
@@ -108,7 +108,8 @@ class BookResolver implements GraphQLResolver /* This class is a resolver
When given a `BookResolver` instance, GraphQL Java Tools first attempts to map fields to methods on the resolver before mapping them to fields or methods on the data class.
If there is a matching method on the resolver, the data class instance is passed as the first argument to the resolver function. This does not apply to root resolvers, since those don't have a data class to resolve for.
-An optional parameter can be defined to inject the `DataFetchingEnvironment`, and must be the last argument.
+The field's arguments come next, in order.
+After them, a method can take any of `DataFetchingEnvironment`, `GraphQLContext` and the `contextClass` set in the [schema parser options]({{< relref "/tools/schema-parser-options/index.md" >}}), in any order.
A resolver also applies to subclasses and implementations of its data class, so a `GraphQLResolver` resolves fields for a data class `Thing extends Base`.
A resolver for a generic class, like `GraphQLResolver>`, applies to every `Page`.
@@ -150,24 +151,32 @@ SchemaParser.newParser()
The field mapping is done by name against public/protected methods and public/protected/private fields, with the following priority:
+`*environmentOrContext` stands for any of `DataFetchingEnvironment`, `GraphQLContext` and the `contextClass`, in any order.
+
First on the resolver or root resolver (note that dataClassInstance doesn't apply for root resolvers):
-1. `method (dataClassInstance, *fieldArgs [, DataFetchingEnvironment])`
-2. `method is(dataClassInstance, *fieldArgs [, DataFetchingEnvironment])`, only if the field returns a `Boolean`
-3. `method get(dataClassInstance, *fieldArgs [, DataFetchingEnvironment])`
-4. `method getField(dataClassInstance, *fieldArgs [, DataFetchingEnvironment])`
+1. `method (dataClassInstance, *fieldArgs [, *environmentOrContext])`
+2. `method is(dataClassInstance, *fieldArgs [, *environmentOrContext])`, only if the field returns a `Boolean`
+3. `method get(dataClassInstance, *fieldArgs [, *environmentOrContext])`
+4. `method getField(dataClassInstance, *fieldArgs [, *environmentOrContext])`
Then on the data class:
-1. `method (*fieldArgs [, DataFetchingEnvironment])`
-2. `method is(*fieldArgs [, DataFetchingEnvironment])`, only if the field returns a `Boolean`
-3. `method get(*fieldArgs [, DataFetchingEnvironment])`
-4. `method getField(*fieldArgs [, DataFetchingEnvironment])`
+1. `method (*fieldArgs [, *environmentOrContext])`
+2. `method is(*fieldArgs [, *environmentOrContext])`, only if the field returns a `Boolean`
+3. `method get(*fieldArgs [, *environmentOrContext])`
+4. `method getField(*fieldArgs [, *environmentOrContext])`
5. `field `
Last of all, if the data class implements`java.util.Map` then:
1. `method get(name)`
+If nothing above matches, a resolver method can leave out the data class instance, as long as it ends in at least one environment or context parameter:
+
+1. `method (*fieldArgs, *environmentOrContext)`, and the `is`, `get` and `getField` forms in the same order as above
+
+This is for fields that only need the environment, e.g. a value the parent field put in its `localContext`. It doesn't apply when `allowUnimplementedResolvers` or a missing resolver data fetcher is set, since those already handle a field with no match.
+
diff --git a/content/tools/schema-parser-options/index.md b/content/tools/schema-parser-options/index.md
index d381efe..00f42e2 100644
--- a/content/tools/schema-parser-options/index.md
+++ b/content/tools/schema-parser-options/index.md
@@ -24,6 +24,8 @@ Options:
```
* `genericWrappers`: Allows defining your own generic classes that should be unwrapped when matching Java types to GraphQL types. You must supply the class and the index (zero-indexed) of the wrapped generic type. For example: If you want to unwrap type argument `T` of `Future`, you must pass `Future.class` and `0`.
Use `GenericWrapper.withTransformer` to also convert the value at runtime. If the transformer returns `null`, the field is `null`.
+ Wrappers and futures nested in lists or in other wrappers are unwrapped too, e.g. `List>` or `List>`. If one element fails, the whole field fails.
+ A transformer or nested future that calls a DataLoader after an async step needs graphql-java's DataLoader chaining (`DataLoaderDispatchingContextKeys.setEnableDataLoaderChaining`), otherwise the field never completes.
* `useDefaultGenericWrappers`: Defaults to `true`. Tells the parser whether or not to add it's own list of well-known generic wrappers, such as `Future` and `CompletableFuture`.
graphql-java only waits on a `CompletionStage`, so a method declared to return a `Future` has to return one, such as a `CompletableFuture`. Any other future fails the field with an error, unless a generic wrapper transformer converts it.