Webflux support
In this release, we added support for Webflux. Webflux support has been one of the most requested features and is now available.
The support includes the following:
- A new module graphql-dgs-reactive. The module contains a new interface
DgsReactiveQueryExecutor
, which is theDgsQueryExecutor
you know and love, but each result is wrapped in aMono
. Internally all query processing is non-blocking. In a Webflux application, both theDgsReactiveQueryExecutor
andDgsQueryExecutor
will be available for injection, so that you can still use the blocking one for things like tests. Internally the Webflux integration usesDgsReactiveQueryExecutor
. - A new module graphql-dgs-spring-webflux-autoconfigure. This module contains the
/graphql
HTTP handler, GraphiQL support and a Websocket endpoint for subscriptions. These endpoints are implemented using Webflux, and the module does not require anywebmvc
modules. - A new starter graphql-dgs-webflux-starter. You use this starter instead of the
graphql-dgs-spring-boot-starter
if you're using DGS in a Webflux environment. - A new example project graphql-dgs-example-java-webflux. This project shares most of the code with the graphql-dgs-example-java, but based on a Webflux stack.
The Webflux integration is obviously a big feature, and we could be missing certain issues and corner cases. Please try it out and report any issues! PRs are always welcome as well.
An example application is available as well: https://github.com/netflix/dgs-examples-webflux
A (breaking) change to DgsRequestData
.
In a recent release we added DgsRequestData
to the DgsContext
. We designed this to be usable both from WebMVC and Webflux, by using the WebRequest
type from Spring's web
module. However, this turned out to be a mistake. Webflux uses a ServerRequest
type instead.
To cleanly fix this issue and not create a suboptimal dependency graph, we made a small breaking change to the API. DgsRequestData
is now an interface, with two implementations: DgsWebMvcRequestData
and DgsReactiveRequestData
. Only if you need access to either WebRequest
or ServerRequest
in your data fetcher, you need to type check and cast to the correct implementation to get access to WebRequest
or ServerRequest
.
If you were using WebRequest
from DgsRequestData
, your code will no longer compile with this release without adding the extra type cast. This should be an easy fix but is the reason we decided on a major release.
A breaking release!?
As explained in the previous paragraph, we had to introduce a change to the DgsRequestData
type. Because this is an API type, this requires a major release. Since this will only impact very specific use cases, it will likely not cause any changes for most users.
We also took the opportunity to remove the previously deprecated DgsContextBuilder
. Remember that this interface has long been obsolete because we have the custom context concept.
Aside from these two changes, there are no other changes affecting backward compatibility. The Webflux modules are optional and don't impact existing WebMVC users.
Scalars in DGS Client
Custom scalars can be used in input types in GraphQL. Let's take the example of a DateRange
scalar that represents a "from" and "to" date.
In Java, we want to represent this as a DateRange class that takes a LocalDate
for the from
and to
fields.
When generating a query API we want to be use the API as follows:
new GraphQLQueryRequest(
ReviewsGraphQLQuery.newRequest().dateRange(new DateRange(LocalDate.of(2020, 1, 1), LocalDate.now())).build(),
new ReviewsProjectionRoot().submittedDate().starScore(), scalars);
When sending the query, we somehow have to serialize this DateRange
though.
There are many ways to represent a date, so how do we make sure that we use the same representation as the server expects?
In this release we added an optional scalars
argument to the GraphQLQueryRequest
constructor.
This is a Map<Class<?>, Coercing<?,?>
that maps the Java class representing the input to an actual Scalar implementation.
This way you can re-use exactly the same serialization code that you already have for your scalar implementation or one of the existing ones from for example the graphql-dgs-extended-scalars
module.
Complete list of changes
- WebFlux support (#301) @paulbakker
- Update example to use dataloader with Try (#316) @srinivasankavitha
- Transient failure on MicrometerServletSmokeTest (#314) @berngp
- Test Example Application as part of the CI Process (#311) @berngp
- Scalar in client (#333) @paulbakker
- Publish the Surefire Reports as part of the Github Actions. (#337) @berngp
- Increment the output on executing the example's tests. (#336) @berngp
- Added TYPE_HIERARCHY strategy to DsgData annotation scanning (#320) @zaenk
- Use AopUtils when looking for @DgsTypeResolver (#327) @paulbakker
- Bug fix to handle query variables in websocket subscriptions. (#332) @srinivasankavitha
- Fix example app config. (#325) @srinivasankavitha
- Escape quotes and backslashes on request serialization (#349) @richardcresswell
- Revert "Update Gradle Wrapper from 6.8.3 to 7.0.2" (#346) @berngp
- Update Gradle Wrapper from 6.8.3 to 7.0.2 (#343) @github-actions
- Serialize Map types in GraphQLQuery (#340) @richardcresswell
- Increase verbosity due a transient test failure. (#341) @berngp
- Disabling CI Test Reports for now (#342) @berngp