github graphql-java-kickstart/graphql-java-tools v14.4.0

latest release: v14.5.0
4 hours ago

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 a GraphQLTypeReference (a wiring on a recursive input field used to fail the build with a ClassCastException). The schema is built and validated before the wirings run, so an invalid schema throws InvalidSchemaException from parseSchemaObjects(), 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 in SchemaObjects point at each other by name until toSchema(). Input object argument types of directives are type references in SchemaObjects too, 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, @specifiedBy and onScalar wiring. The provided scalar's specifiedByUrl (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 in SchemaObjects.dictionary now and referred to by name, so a schema built from parseSchemaObjects() without additionalTypes(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 app ValueUnboxer that 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 repeatable now logs a WARN from graphql.kickstart.tools.SchemaParser that points at the line in the SDL. These become errors in 15.0.0 (#884). If you copied directive @connection(for: String!) on FIELD from our tests, declare it on FIELD_DEFINITION.
  • Missing resolver parameters (#890, fixes #418): a resolver method that's missing the parameter for an argument, where a DataFetchingEnvironment, GraphQLContext or 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) and foo(ctx, env), both match now and the first one found wins. Before, only foo(env) matched.

New

  • Resolver methods can take the context and DataFetchingEnvironment together, in any order, after the schema arguments (#888).
  • A GraphQLResolver<T> method can leave out the source object when it ends in a DataFetchingEnvironment, GraphQLContext or context class parameter, e.g. fun imageBlob(env: DataFetchingEnvironment) (#904, fixes #304). It's only used when nothing else matches the field, and not when allowUnimplementedResolvers or a missing resolver data fetcher is set.
  • SchemaParserDictionary.toMap() returns the dictionary as a plain Map<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-CompletionStage Future behind a type variable returned its toString(), and a subscription returning a Publisher subtype 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 Box returned as Any resolves to StringBox when Box<String> backs StringBox (#892).
  • A nested list argument for a parameter with a non-List inner collection, e.g. [[String]] for List<Set<String>>, is converted instead of failing with a ClassCastException (#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 with Cannot construct instance of Badge (#904).

Deprecations

  • SchemaParserDictionary.getDictionary() and graphql.kickstart.tools.util.BiMap are deprecated, use SchemaParserDictionary.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

Don't miss a new graphql-java-tools release

NewReleases is sending notifications on new releases.