Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions content/tools/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ menu:
parent: Tools
---

[![Maven Central](https://img.shields.io/maven-central/v/com.graphql-java-kickstart/graphql-java-tools.svg)](https://maven-badges.herokuapp.com/maven-central/com.graphql-java-kickstart/graphql-java-tools)
[![TravisCI Build](https://travis-ci.org/graphql-java-kickstart/graphql-java-tools.svg?branch=master)](https://travis-ci.org/graphql-java-kickstart/graphql-java-tools)
[![Maven Central](https://maven-badges.sml.io/maven-central/io.github.graphql-java-kickstart/graphql-java-tools/badge.svg)](https://central.sonatype.com/artifact/io.github.graphql-java-kickstart/graphql-java-tools)
[![Github Build](https://github.com/graphql-java-kickstart/graphql-java-tools/actions/workflows/snapshot.yml/badge.svg)](https://github.com/graphql-java-kickstart/graphql-java-tools/actions/workflows/snapshot.yml)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=graphql-java-kickstart_graphql-java-tools&metric=alert_status)](https://sonarcloud.io/dashboard?id=graphql-java-kickstart_graphql-java-tools)
[![GitHub contributors](https://img.shields.io/github/contributors/graphql-java-kickstart/graphql-java-tools)](https://github.com/graphql-java-kickstart/graphql-java-tools/graphs/contributors)
[![Discuss on GitHub](https://img.shields.io/badge/GitHub-discuss-orange)](https://github.com/graphql-java-kickstart/graphql-java-tools/discussions)
Expand Down
10 changes: 9 additions & 1 deletion content/tools/directives/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ menu:
url: /tools/directives/
---

See [Schema Directives](https://www.graphql-java.com/documentation/v16/sdl-directives/)
See [Schema Directives](https://www.graphql-java.com/documentation/directives)
for a detailed explanation about directives including examples on how to define
them in the SDL and to create the required classes.

Expand Down Expand Up @@ -67,6 +67,12 @@ SchemaParser.newParser()
.makeExecutableSchema();
```

If several wirings apply to the same element, each one gets the element returned by the previous one.

Arguments the SDL leaves out are filled in with their default from the directive definition, so the wiring sees the default instead of `null`.

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.

## Supported locations
Support for directives is currently limited to the following locations:

Expand All @@ -83,3 +89,5 @@ Support for directives is currently limited to the following locations:
Meaning directives for the following locations are currently not yet supported:

* `SCALAR`

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" >}}).
19 changes: 11 additions & 8 deletions content/tools/getting-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Add the `graphql-java-tools` dependency:

```gradle
dependencies {
compile 'com.graphql-java-kickstart:graphql-java-tools:13.0.3'
implementation 'io.github.graphql-java-kickstart:graphql-java-tools:14.3.0'
}
```

Expand All @@ -44,15 +44,15 @@ Add the `graphql-java-tools` dependency:

```xml
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<groupId>io.github.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>13.0.3</version>
<version>14.3.0</version>
</dependency>
```

## Using the latest development build

Snapshot versions of the current `master` branch are available on JFrog. Check the next snapshot version on
Snapshot versions of the current `master` branch are available on the Maven Central snapshot repository. Check the next snapshot version on
[Github](https://github.com/graphql-java-kickstart/graphql-java-tools/blob/master/pom.xml#L7)

### Build with Gradle
Expand All @@ -62,7 +62,7 @@ Add the Snapshot repository:
```gradle
repositories {
mavenCentral()
maven { url "https://oss.jfrog.org/artifactory/oss-snapshot-local" }
maven { url = 'https://central.sonatype.com/repository/maven-snapshots/' }
}
```

Expand All @@ -73,9 +73,12 @@ Add the Snapshot repository:
```xml
<repositories>
<repository>
<id>oss-snapshot-local</id>
<name>jfrog</name>
<url>https://oss.jfrog.org/artifactory/oss-snapshot-local</url>
<id>central-portal-snapshots</id>
<name>Central Portal Snapshots</name>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
Expand Down
31 changes: 30 additions & 1 deletion content/tools/schema-definition/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ SchemaParser.newParser()
Query { }
```
Multiple sources will be concatenated together in the order given, allowing you to modularize your schema if desired.
Line numbers in syntax errors count from the start of each file or string, and errors in a file end with its name. To name a schema string too, pass the name as well:

```java
SchemaParser.newParser()
.schemaString(usersSchema, "users.graphqls")
```

## Resolvers and Data Classes

Expand Down Expand Up @@ -104,6 +110,17 @@ When given a `BookResolver` instance, GraphQL Java Tools first attempts to map f
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.

A resolver also applies to subclasses and implementations of its data class, so a `GraphQLResolver<Base>` resolves fields for a data class `Thing extends Base`.
A resolver for a generic class, like `GraphQLResolver<Page<?>>`, applies to every `Page<T>`.
When several resolvers apply, the one for the most specific type is tried first.

In Kotlin, a resolver method can also be an extension function on the data class:
```kotlin
class BookResolver(private val authorRepository: AuthorRepository) : GraphQLResolver<Book> {
fun Book.author(): Author = authorRepository.findById(authorId)
}
```

### Root Resolvers

Since the Query/Mutation/Subscription objects are root GraphQL objects, they don't have an associated data class. In those cases, any resolvers implementing `GraphQLQueryResolver`, `GraphQLMutationResolver`, or `GraphQLSubscriptionResolver` will be searched for methods that map to fields in their respective root types. Root resolver methods can be spread between multiple resolvers, but a simple example is below:
Expand Down Expand Up @@ -156,7 +173,7 @@ Last of all, if the data class implements`java.util.Map` then:

*Note:* Methods on `java.lang.Object` are excluded from method matching, for example a field named `class` will require a method named `getFieldClass` defined.

*Note:* If one of the values of a type backed by a `java.util.Map` is non-scalar then this type will need to be added to the `type dictionary` (see below). After adding this type to the dictionary, GraphQL Java Tools will however still be able to find the types used in the fields of this added type.
*Note:* If one of the values of a type backed by a `java.util.Map` is non-scalar, on its own or in a list, then this type will need to be added to the `type dictionary` (see below). After adding this type to the dictionary, GraphQL Java Tools will however still be able to find the types used in the fields of this added type.

## Enum Types

Expand Down Expand Up @@ -187,6 +204,7 @@ class AdditionInput {
## Interfaces and Union Types

GraphQL interface/union types are automatically resolved from the schema and the list of provided classes, and require no extra work outside of the schema.
Members and implementors that no resolver returns need to be in the [type dictionary](#type-dictionary), unless the class of their union or interface is sealed.
Although not necessary, it's generally a good idea to have java interfaces that correspond to your GraphQL interfaces to keep your code understandable.

## Scalar Types
Expand All @@ -213,6 +231,17 @@ SchemaParser.newParser()
.dictionary("Book", BookClassWithIncorrectName.class)
```

Several input types can share a class, e.g. Jackson's `ObjectNode`. Other types need a class each.

If the class of a union or interface is a Kotlin sealed class or interface, or a Java sealed type, its members and implementors don't need to be added. GraphQL Java Tools uses the subclass with the same simple name as the GraphQL type:
```kotlin
// union Pet = NormalPet | WeirdPet
sealed class Pet {
data class NormalPet(val name: String) : Pet()
data class WeirdPet(val classification: String) : Pet()
}
```

## Making the graphql-java Schema Instance

After you've passed all relevant schema files/class to the parser, call `.build()` and `.makeExecutableSchema()` to get a graphql-java `GraphQLSchema`:
Expand Down
17 changes: 15 additions & 2 deletions content/tools/schema-parser-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ Options:
.graphQLContext(Map.of(CustomContext.class, context));
```
* `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<T>`, 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`.

* `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.
* `allowUnimplementedResolvers`: Defaults to `false`. Allows a schema to be created even if not all GraphQL fields have resolvers. Intended only for development, it will log a warning to remind you to turn it off for production. Any unimplemented resolvers will throw errors when queried.
* `missingResolverDataFetcher`: Allows you to provide custom behavior for missing GraphQL fields.
* `inputArgumentOptionalDetectOmission`: Defaults to `false`. By default, the parser will treat omitted or null method input arguments as `Optional.empty` in resolvers. If you prefer, you can disable this behavior.
Expand Down Expand Up @@ -53,8 +55,19 @@ Options:
* Guice
* Spring AOP
* Weld
* `introspectionEnabled`: Defaults to `true`. When set to `false` this option will disable schema introspection via `NO_INTROSPECTION_FIELD_VISIBILITY`. See [Field Visibility](https://www.graphql-java.com/documentation/master/fieldvisibility/).
* `fieldVisibility`: Provide a graphql field visibility implementation. This option overrides `introspectionEnabled` when used. See [Field Visibility](https://www.graphql-java.com/documentation/master/fieldvisibility/).
* `introspectionEnabled`: Defaults to `true`. When set to `false` this option will disable schema introspection via `NO_INTROSPECTION_FIELD_VISIBILITY`. See [Field Visibility](https://www.graphql-java.com/documentation/field-visibility).
* `fieldVisibility`: Provide a graphql field visibility implementation. This option overrides `introspectionEnabled` when used. See [Field Visibility](https://www.graphql-java.com/documentation/field-visibility).
* `coroutineContext` / `coroutineContextProvider`: Provide a kotlin coroutine context to be used with suspend functions of resolvers.
A suspend function runs on the calling thread until it first suspends, and continues on this context after that, so wrap blocking calls in `withContext(Dispatchers.IO)`.
To run them in your own `CoroutineScope`, e.g. to cancel them with the request, put it in the execution input's context:
```java
var executionInput = ExecutionInput.newExecutionInput()
.query(query)
.graphQLContext(Map.of(CoroutineScope.class, scope));
```
* `typeDefinitionFactory`: See [Type Definition Factory]({{< relref "/tools/type-definition-factory/index.md" >}}).
* `includeUnusedTypes`: Defaults to `false`. By default, the parser will ignore unused type definitions in the schema. Enable this option to include them regardless.
* `allowUndeclaredDirectives`: Defaults to `false`. Allows applying directives that aren't declared in the schema, e.g. the Apollo Federation directives imported through `@link`. They're only added as applied directives, with argument types guessed from their values. Directives with enum or input object arguments still have to be declared.
* `unmappedInputFields`: Defaults to `WARN`. What to do about input type fields that the class of a resolver argument has no property for. When a client sends such a field, Jackson fails to convert the argument, or drops the value if the `ObjectMapper` ignores unknown properties.
The classes are checked when the schema is built, with each field's own `ObjectMapper`, and `WARN` logs a warning for each of these fields. `FAIL` fails the build instead, and `IGNORE` skips the check. To leave a field unmapped on purpose, add it to `@JsonIgnoreProperties` on the class.
Classes with a custom deserializer, a builder or a delegating creator aren't checked, and neither are arguments bound to a `Map` or a `JsonNode`.