Skip to content

Releases: graphql-java/graphql-java

18.0

15 Mar 09:17
470811b
Compare
Choose a tag to compare

We are happy to announce v18.0 of graphql-java

https://github.com/graphql-java/graphql-java/pulls?q=is%3Apr+milestone%3A18.0+is%3Aclosed

Applied Directives

Graphql directives have two modes. They can be defined in a schema

directive @example on FIELD_DEFINITION | ARGUMENT_DEFINITION

and they can be applied to schema elements and query elements

type Query {
   field(arg : String! ) @example

So we have a directive definition and cases where that directive is applied to an element.

However when the graphql.schema.GraphQLDirective and graphql.schema.GraphQLArgument classes was created, we modelled this badly. These classes should really represent a directive definition in schema only but we reused them to also be the representation of a directive and value arguments applied to another schema or query element.

This modelling is wrong. You can tell because we have javadoc comments like this in graphql.schema.GraphQLArgument saying a certain property is only applicable in certain call contexts.

    /**
     * This is only used for applied directives, that is when this argument is on a {@link GraphQLDirective} applied to a schema or query element
     *
     * @return an input value with state for an applied directive
     *
     * @deprecated use {@link GraphQLAppliedDirectiveArgument} instead
     */
    @Deprecated
    public @NotNull InputValueWithState getArgumentValue() {
        return value;
    }

So we have decided to fix this bad class modelling in version 18. We have introduced new classes

  • graphql.schema.GraphQLAppliedDirective
  • graphql.schema.GraphQLAppliedDirectiveArgument

which represent an applied directive on a schema element and

  • graphql.execution.directives.QueryAppliedDirective
  • graphql.execution.directives.QueryAppliedDirectiveArgument

which represent an applied directive on a query element

For backwards compatibility reasons, the old graphql.schema.GraphQLDirective objects are still created for applied elements however the methods have all been deprecated and like for like getAppliedXXX methods have been introduced.

You should migrate your code way from getting applied directives from the old methods and use the new more correctly modelled classes. This backwards compatibility will be removed in a future version.

Because of this backwards compatibility, there are a few gotchas to look out for. For example visitors will be called twice for the same applied element, eg one for the old style GraphQLDirective object and one for the new GraphQLAppliedDirective object. You should choose the new classes only as part of code migration. This should only affect code that does schema and query traversal (which is an advanced use case) and hence most consumers of graphql-java will not be affected.

There is one breaking change here. graphql.introspection.IntrospectionWithDirectivesSupport and its predicate argument graphql.introspection.IntrospectionWithDirectivesSupport.DirectivePredicateEnvironment have been changed to provide a directive name and not the appliedGraphQLDirective directly. Again we think very few people will be affected by this breaking change.

#2186

Dramatic performance improvement on Validation rules

The team at Twitter contributed a changed to the RulesVisitor that is used to validate a query against the set of validation rules. For large queries this could be a performance drag.

This changes it to roughly linear complexity and shows a 5000% speedup when validating our large queries.

#2563

Skipping validation rules

In extreme cases, a server may choose to skip certain validation rules. We don't recommend it, because results may become unpredictable and we won't support fixing issues caused by deactivated rules.

However it is now possible and may help trade validation for performance.

 Predicate<Class<?>> predicate = new Predicate<Class<?>>() {
            @Override
            boolean test(Class<?> aClass) {
                if (aClass == NoUnusedFragments.class) {
                    return false
                }
                return true
            }
        }
        
ExecutionInput.newExecutionInput(query)
                .graphQLContext(["graphql.ParseAndValidate.Predicate": predicate])
                .build()

#2598

DataLoader has been upgrade

The java data loader version has been upgrade to 3.1.2 which as some bug fixes and small improvements.

#2724

PreparsedDocumentProvider changes

The graphql.execution.preparsed.PreparsedDocumentProvider has been updated to use a CompletableFuture<PreparsedDocumentEntry> getDocumentAsync method. This allows you to go to a remote cache in an asynchronous non blocking manner to get cached documents. This should have always been modelled in this manner.

However its an optional default interface method thats called the old deprecated synchronous method direct.

https://github.com/graphql-java/graphql-java/pull/2612/files

AstPrinter performance

The AST printer has been improved to stop unnecessary string allocation. For very large queries this slowed printing down dramatically.

#2729

Local context and field selection in TypeResolutionEnvironment

The type resolvers now can get access to the local context object via the passed in graphql.TypeResolutionEnvironment interface.

Similarly, the field sub selection graphql.schema.DataFetchingFieldSelectionSet is also now available.

#2699
#2597

Auto generated list of What's Changed

  • This adds the AST definitions onto applied directives and applied arguments by @bbakerman in #2556
  • Adding a parser listener AND the ability to set parser options per request by @bbakerman in #2555
  • Add InstrumentationValidationParameters to QueryComplexityInfo by @stevenleeDB in #2558
  • A protected method for logging by @bbakerman in #2569
  • Improve non-nullable argument exception in ValuesResolver by @dondonz in #2572
  • Support for custom validation error by @dugenkui03 in #2528
  • Fix triple nested enum validation error by @dondonz in #2570
  • Sort schema directives in SchemaPrinter. by @folone in #2575
  • Only publish with Maven POM, disable Gradle module metadata file by @dondonz in #2586
  • Override ImmutableMapWithNullValues.toString() (#2568) by @fvasco in #2594
  • Fixed a bug in NormalisedInputValue by @bbakerman in #2599
  • Compatator is used for in order schema printing by @russellyou in #2606
  • The ability to sort a schema during printing by @bbakerman in #2561
  • Support for tracking the parse order by @bbakerman in #2539
  • fix broken build by @russellyou in #2607
  • Added support for a context object to the AstTransformer by @chriswr95 in #2596
  • Add type reference support to interface builders by @dondonz in #2602
  • Fix integration test using the default Locale in Locale#getDisplayName() by @jord1e in #2611
  • Avoid printing inline fragment if there is no conditional type by @gnawf in #2621
  • fix typos in javadoc by @dfa1 in #2619
  • Simplify some isEqualTo implementations by @dfa1 in #2620
  • It's hard to search for failed in test output when we say this a lot.… by @bbakerman in #2629
  • change preparsedDocumentProvider return value to CompletableFuture by @heoYH in #2612
  • Propagate errors to individual Subscription events by @jord1e in #2610
  • Directive validation is now done on schema build post validation by @bbakerman in #2576
  • Using custom data structure for callstack tracking by @dfa1 in #2630
  • Naming fix up to IntMap by @bbakerman in #2631
  • Only print out important tests by @bbakerman in #2632
  • A default implementation of DataFetcherExceptionHandler.onException by @bbakerman in #2614
  • Correct broken links to documentation site by @jamietanna in #2640
  • Allow leading pipe in directive SDL, and add leading union pipe tests by @jord1e in #2650
  • Bugfix: Check wiring factory when fetching scal...
Read more

17.3

19 Sep 01:00
Compare
Choose a tag to compare

This bug fix version of graphql-java provides new limits to help prevent Denial Of Service attacks induced by over parsing and validation.

Attackers can craft queries that consume lot of resources to parse and validate, which which ultimately invalid can deny real queries from being serviced.

#2549

#2553

There are new limits imposed by default. Parsing will be terminated after 1500 tokens and only 100 validation errors will be captured.

We chose to put in defaults so that people will get some amount of bad query parse and validate DOS protection out of the box.

There are JVM wide methods to change the default on these if that's problematic for your implementation.

There is also a small fix in the ValueResolver

8530366

17.2

27 Aug 04:29
27b11d9
Compare
Choose a tag to compare

This is a bugfix release which contains the following changes:

https://github.com/graphql-java/graphql-java/milestone/36?closed=1

17.1

10 Aug 01:02
452abc9
Compare
Choose a tag to compare

Upgrade to DataLoader 3.1.0

This release upgrade the DataLoader library to 3.1.0 which adds the ability to have an external value cache in place during data loader batch calls.

You can use it to model access to external caches like REDIS amd even do batch "cache gets".

17.0

03 Aug 08:10
fd86181
Compare
Choose a tag to compare

We are happy to announce v17.0 of graphql-java

https://github.com/graphql-java/graphql-java/milestone/31?closed=1

@deprecated supported on input fields

In line with coming graphql spec changes, the @deprecated annotation can now be placed on input fields and not just output fields as before.

#2186

Dramatic performance improvements in GraphQLSchema building

The GraphQLSchema is a graph of types and as such has to be built according to strict rules. The previous code would repeated visit and rebuilt the schema and this meant that large schemes could be slow to build.

This code has been extensively benchmarked and improved. For example on a very large and complex schema, total build time went from 3.5 seconds to 1.2 seconds.

Thank you to teams out there that used https://github.com/graphql-java/graphql-anonymizer to submit in real life schemas that we can test with.

Dramatic performance improvements in DataFetchingFieldSelectionSet

The classes that underlie the DataFetchingFieldSelectionSet code have been been remodelled to be dramatically more performant. Before interfaces could create an exponential explosion in objects created. This has been fixed which in turn improves the performance of this code as scale.

Dramatic performance improvements in large query validation

The graphql spec calls for overlapping fields in fragments to be validated in a certain way. The previous code followed the specs psudeo-algorithm correctly but it leads to asymptotic performance problems.

This has been rewritten via #2495 based on this article https://tech.xing.com/graphql-overlapping-fields-can-be-merged-fast-ea6e92e0a01 which dramatically improves how fast large queries can validated.

Support of directives on fields and types during introspection

#2221 this is a non spec feature which lets you expose directives through Introspection

Reworked default value validation and improved Scalar coercion

#2325 This is a relatively big change which fixed up how default values are processed. Before that default values were never validated and custom Scalars could cause invalid values printed in SDL or Introspection. This PR includes a new Scalar coercion function valueToLiteral which is needed to implement this correct behaviour.

Better Unicode support in documents

#2404 allows for better Unicode expression in queries and SDL documents

GraphQLContext is now the approved context mechanism

#2368 allows for a well known API for context within a graphql request. Previously any opaque object could be used and framework could was not able to make any assumptions about adding their own context properties

The old mechanism has been deprecated and a singleton (buy mutable) context object is now how context is passed around.

Ignored characters are no longer help in memory by default

Characters in a graphql document that are not significant to the syntax, such as spaces, new lines and comms, used to be captured in memory against AST nodes.

This is no longer the case and it saves memory from parsed documents. There is a switch to turn on the old behavior intended for tooling code.

#2394

Exception handlers can now be asynchronous

graphql-java operates in a asynchronous world and hence the code that handles exceptions in data fetchers should itself allow asynchronous handling.

#2371

Non standard scalars have been removed

graphql-java used to have non standard scalars like Byte, Short and Long etc... These deprecated scalars have finally been removed and now reside in the https://github.com/graphql-java/graphql-java-extended-scalars library

Breaking changes

https://github.com/graphql-java/graphql-java/pulls?q=is%3Apr+label%3A%22breaking+change%22++milestone%3A%2217.0%22

  • The boolean values acceptable as variable input the Boolean scalar have been tightened to true and false - see #2419

  • The non standard @Fetch directive support has been removed by default and deprecated. This was done for performance reasons because very few people used it but it slowed down schema creation a lot

  • The long deprecated BatchedExecutionStrategy and ExecutorServiceExecutionStrategy have finally been removed

  • The non standard scalars like Long and Short have been removed and moved to https://github.com/graphql-java/graphql-java-extended-scalars

17.0-beta1

20 Jul 00:55
128e3d5
Compare
Choose a tag to compare

An initial beta 1 release of 17.0.

We consider this production ready, but we are seeking feedback from early adopters, therefor the beta1 release.

https://github.com/graphql-java/graphql-java/milestone/31?closed=1

@deprecated supported on input fields

In line with coming graphql spec changes, the @deprecated annotation can now be placed on input fields and not just output fields as before.

#2186

Dramatic performance improvements in GraphQLSchema building

The GraphQLSchema is a graph of types and as such has to be built according to strict rules. The previous code would repeated visit and rebuilt the schema and this meant that large schemes could be slow to build.

This code has been extensively benchmarked and improved. For example on a very large and complex schema, total build time went from 3.5 seconds to 1.2 seconds.

Thank you to teams out there that used https://github.com/graphql-java/graphql-anonymizer to submit in real life schemas that we can test with.

Dramatic performance improvements in DataFetchingFieldSelectionSet

The classes that underlie the DataFetchingFieldSelectionSet code have been been remodelled to be dramatically more performant. Before interfaces could create an exponential explosion in objects created. This has been fixed which in turn improves the performance of this code as scale.

Upgrade to DataLoader 3.x

https://github.com/graphql-java/java-dataloader has been upgraded to the new 3.0.1 version which adds new capabilities on external value caching.

Support of directives on fields and types during introspection

#2221 this is a non spec feature which lets you expose directives through Introspection

Reworked default value validation and improved Scalar coercion

#2325 This is a relatively big change which fixed up how default values are processed. Before that default values were never validated and custom Scalars could cause invalid values printed in SDL or Introspection. This PR includes a new Scalar coercion function valueToLiteral which is needed to implement this correct behaviour.

Better Unicode support in documents

#2404 allows for better Unicode expression in queries and SDL documents

GraphQLContext is now the approved context mechanism

#2368 allows for a well known API for context within a graphql request. Previously any opaque object could be used and framework could was not able to make any assumptions about adding their own context properties

The old mechanism has been deprecated and a singleton (buy mutable) context object is now how context is passed around.

Ignored characters are no longer help in memory by default

Characters in a graphql document that are not significant to the syntax, such as spaces, new lines and comms, used to be captured in memory against AST nodes.

This is no longer the case and it saves memory from parsed documents. There is a switch to turn on the old behavior intended for tooling code.

#2394

Exception handlers can now be asychronous

graphql-java operates in a asynchronous world and hence the code that handles exceptions in data fetchers should itself allow asynchronous handling.

#2371

Breaking changes

https://github.com/graphql-java/graphql-java/pulls?q=is%3Apr+label%3A%22breaking+change%22++milestone%3A%2217.0%22

  • The boolean values acceptable as variable input the Boolean scalar have been tightened to true and false - see #2419

  • The non standard @Fetch directive support has been removed by default and deprecated. This was done for performance reasons because very few people used it but it slowed down schema creation a lot

  • The new DataLoader upgrade has changed the signature of the future cache to be more correct.

  • The long deprecated BatchedExecutionStrategy and ExecutorServiceExecutionStrategy have finally been removed

Version 16.2

02 Feb 05:48
Compare
Choose a tag to compare

This is a bugfix release containing the following fixes and improvements:

https://github.com/graphql-java/graphql-java/milestone/33?closed=1

The most important ones are

#2168 Bugfix: caching of visited fragments in Normalized tree
#2173 Ensure NormalizedQueryTreeFactory handles mutations and subscriptions

16.1

25 Nov 04:00
43668fb
Compare
Choose a tag to compare

This is a bugfix release for the 16.0 version: Checkout the full 16.0 release notes

graphql-java shades in the Google immutable collections.

However we missed a package that was required and #2107 was the result.

This has been fixed in this 16.1 release.

Additionally it contains two other PRs:

#2113 Introspection for repeatable directive

#2111 Fixes module name

16.0

21 Nov 04:43
3dfeae3
Compare
Choose a tag to compare

Please don't use 16.0, but rather 16.2

After a very lengthy time between releases, we are happy to announce that v16.0 of graphql-java is now available.

It adds new capabilities based on updated graphql specification and as usual a mix of bug fixes and performance improvements.

#2015 Repeatable directives support

The graphql specification now allows repeated directives on an element. This adds support for this. The is a breaking change because now there can be more than 1 directives for a given name and this was not true prior to this release.

#2079 Support in DataFetchingFieldSelectionSet for Unions and Interfaces

We have revamped the DataFetchingFieldSelectionSet so that it can handle non concrete types such as Unions. This is a breaking change but it significantly increases the ability to look ahead at all "possible" field selections and hence allow you to
do your own data retrieval optimisations even better.

#2093 Makes a default data fetcher exception handler possible

It is now easier to customise the data fetcher exception handler, without requiring you to instantiate your own execution strategies.

More schema validation

The validation code that ensures the schema conforms to specification has been improved. We have more SDL based validation and also we have post schema building validation to ensure types are specification compliant.

#2013 Persistent query support

We have added more code to help better support persistent queries. This includes basic implementations of the Apollo pattern for nominating persistent queries via query input extensions.

#2086 Use Immutable collections to avoid memory copying

As we worked towards releasing v16.0 we decided to attack the immutability of the objects
used in the code base. We reasoned that Immutable data structures would be more reliable
and they MAY be faster as less list / map copying needs to happen in order to pass
data around.

One thing that graphql-java does a lot of is pass a lot of lists and maps around. A graphql
engine is by specification a giant list and map generator.

We reasoned that because Immutable collections can do tricks when copying data (if its already immutable it can just no-op the copy)
then this may favour our code base.

   List<Foo> fooList = ImmutableList.of("a","b","c");
   //
   // no actual copying takes place in this classes because
   // the list is an immutable collection already
   //
   List<Foo> copiedFooList = ImmutableList.copyOf(fooList);

Benchmarks of the code confirmed this to be faster and also reduce memory pressure..

Performance improvements and memory pressure improvements

We have a lot of performance improvements in this release. Some of them are significant improvements for systems at high scale.

#2008 changed the error holder class
#2019 Faster Property fetching with derived classes
#2020 pre-sizing internal data structures
#2067 Support for Streams and Iterators
#2074 avoiding allocations in FieldCollectorParameters and MergedField
#2086 Use Immutable collections to avoid memory copying
#2023 ExecutionStepInfo optimisations to make it more performant

All breaking changes

All PRs for 16.0

Version 14.1

29 May 04:15
Compare
Choose a tag to compare

This is the first bugfix release for the current LTS 14.x.

List of all Bugfixes