Behaviour changes
Nothing public was removed. Most of these only matter if you register a SchemaDirectiveWiring, return wrappers nested in lists, or read parseSchemaObjects() directly.
- Directive wirings (#895, fixes #875): wirings now run on the assembled schema, like graphql-java's
SchemaGenerator, so they see the real types everywhere instead of aGraphQLTypeReference(a wiring on a recursive input field used to fail the build with aClassCastException). The schema is built and validated before the wirings run, so an invalid schema throwsInvalidSchemaExceptionfromparseSchemaObjects(), and a wiring can't make an invalid schema valid anymore. Building is slower with a wiring registered, since the schema is built and validated twice: about 75 ms -> 90 ms on a ~600 type schema. Schemas without wirings aren't affected. When a wiring changes a type, the types inSchemaObjectspoint at each other by name untiltoSchema(). Input object argument types of directives are type references inSchemaObjectstoo, with or without wirings. The unmapped input field check now runs on the wired input objects and reports after the other schema errors. - Scalars (#894, fixes #864): custom scalars get the directives of their definition and extensions,
@specifiedByandonScalarwiring. The provided scalar'sspecifiedByUrl(e.g. from extended scalars) now shows up in introspection. ⚠️ An undeclared directive or an unknown argument on a scalar logs a WARN and the scalar is built without its SDL directives. This becomes an error in 15.0.0 (#893). A directive argument on a scalar whose value doesn't fit its type (@specifiedBy(url: 5)) now fails the build, like on every other type. Custom scalars are inSchemaObjects.dictionarynow and referred to by name, so a schema built fromparseSchemaObjects()withoutadditionalTypes(dictionary)fails. - Nested wrappers and futures (#903, fixes #254): a generic wrapper or future nested in a list or in another wrapper (
List<Try<Payload>>,List<CompletableFuture<Item>>,CompletableFuture<CompletableFuture<Item>>) is now unwrapped instead of failing every query. If one element fails, the whole field fails with one error, where an appValueUnboxerthat nulled failed elements used to give a null element. A transformer or nested future that calls a DataLoader after an async step needs graphql-java's DataLoader chaining (DataLoaderDispatchingContextKeys.setEnableDataLoaderChaining) enabled, otherwise the field never completes. Subscriptions, property fields and custom scalars aren't unwrapped, same as before. - Misused directives (#885, fixes #225): a directive applied where its definition doesn't allow it, missing a required argument, or repeated without being
repeatablenow logs a WARN fromgraphql.kickstart.tools.SchemaParserthat points at the line in the SDL. These become errors in 15.0.0 (#884). If you copieddirective @connection(for: String!) on FIELDfrom our tests, declare iton FIELD_DEFINITION. - Missing resolver parameters (#890, fixes #418): a resolver method that's missing the parameter for an argument, where a
DataFetchingEnvironment,GraphQLContextor context class parameter takes its place, now logs a WARN at build. The field still fails at query time like before. This becomes an error in 15.0.0 (#889). - Output types sharing a class (#901, fixes #861): still fail the build, but with
Class 'X' is used for types 'Book', 'Movie', but only input object types can share a class!instead of "Error creating bimap of type => class". - Overloaded resolver methods (#888): if a class has both
foo(env)andfoo(ctx, env), both match now and the first one found wins. Before, onlyfoo(env)matched.
New
- Resolver methods can take the context and
DataFetchingEnvironmenttogether, in any order, after the schema arguments (#888). - A
GraphQLResolver<T>method can leave out the source object when it ends in aDataFetchingEnvironment,GraphQLContextor context class parameter, e.g.fun imageBlob(env: DataFetchingEnvironment)(#904, fixes #304). It's only used when nothing else matches the field, and not whenallowUnimplementedResolversor a missing resolver data fetcher is set. SchemaParserDictionary.toMap()returns the dictionary as a plainMap<String, Class<*>>(#901).
Fixes
- Resolver methods inherited from a generic class resolve the class's type variables in their parameter types (#882, fixes #880) and return types (#883). Before, a parameter typed by a type variable failed every query with a
ClassCastException, a non-CompletionStageFuturebehind a type variable returned itstoString(), and a subscription returning aPublishersubtype through a type variable didn't build. - A union that's only a member of other unions builds (#887, fixes #866). Unions that contain themselves fail with an error naming the cycle instead of a
StackOverflowError(#902, fixes #886). - A union or interface field resolves a value of a generic class to the type its parameterized return type backs, e.g. a
Boxreturned asAnyresolves toStringBoxwhenBox<String>backsStringBox(#892). - A nested list argument for a parameter with a non-
Listinner collection, e.g.[[String]]forList<Set<String>>, is converted instead of failing with aClassCastException(#891). SchemaObjects.toReadOnlySchema()works with interfaces, unions, custom directives and schema directives (#894, #898, fixes #896).- A resolver declared by its own data class (
class Badge : GraphQLResolver<Badge>) no longer fails every query withCannot construct instance of Badge(#904).
Deprecations
SchemaParserDictionary.getDictionary()andgraphql.kickstart.tools.util.BiMapare deprecated, useSchemaParserDictionary.toMap()instead. Both will be removed in 15.0.0 (#900).
What's Changed
- Version Release by @github-actions[bot] in #873
- Remove the Maven 3.9 pin from the release workflow by @oryan-block in #874
- Run the Version Release PR checks through GitHub's workflow approval by @oryan-block in #877
- Test the schema warnings through a shared log-capture helper by @oryan-block in #878
- Query every field of every test schema by @oryan-block in #879
- Resolve type variables in resolver parameter types by @oryan-block in #882
- Resolve type variables in resolver return types by @oryan-block in #883
- Allow resolver methods to take both the context and the environment by @oryan-block in #888
- Warn about directives applied where their definition doesn't allow them by @oryan-block in #885
- Build unions that are only members of other unions by @oryan-block in #887
- Warn at build when a resolver method is missing a parameter for an argument by @oryan-block in #890
- Check scalar arguments when building the schema by @oryan-block in #891
- Resolve union and interface values by the raw class of a parameterized type by @oryan-block in #892
- Run directive wirings on the assembled schema by @oryan-block in #895
- Apply directives and @specifiedBy to scalars by @oryan-block in #894
- Determine input types with the same recursion as output types by @oryan-block in #897
- Build the read-only schema with the code registry and schema directives by @oryan-block in #898
- Build applied and legacy directives from one resolved list by @oryan-block in #899
- Replace BiMap with plain maps by @oryan-block in #901
- Fail with a clear error when unions contain themselves by @oryan-block in #902
- Unwrap generic wrappers and futures nested in lists and other wrappers by @oryan-block in #903
- Allow resolver methods that leave out the source object by @oryan-block in #904
- Split SchemaClassScanner and SchemaParser into smaller classes by @oryan-block in #906
Full Changelog: v14.3.0...v14.4.0