Releases: graphql-java/graphql-java
18.0
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.
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.
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()
DataLoader has been upgrade
The java data loader version has been upgrade to 3.1.2
which as some bug fixes and small improvements.
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.
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.
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...
17.3
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.
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
17.2
This is a bugfix release which contains the following changes:
https://github.com/graphql-java/graphql-java/milestone/36?closed=1
17.1
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
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.
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.
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.
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
-
The boolean values acceptable as variable input the Boolean scalar have been tightened to
true
andfalse
- 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
andExecutorServiceExecutionStrategy
have finally been removed -
The non standard scalars like
Long
andShort
have been removed and moved to https://github.com/graphql-java/graphql-java-extended-scalars
17.0-beta1
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.
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.
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.
Breaking changes
-
The boolean values acceptable as variable input the Boolean scalar have been tightened to
true
andfalse
- 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
andExecutorServiceExecutionStrategy
have finally been removed
Version 16.2
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
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
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
This is the first bugfix release for the current LTS 14.x.