Skip to content

Commit 1979e43

Browse files
committed
Upgrade to GraphQL Java 22.2
This also documents the new subscription ordering feature as reported and requested in #949. Closes gh-1044
1 parent 311531b commit 1979e43

File tree

5 files changed

+122
-15
lines changed

5 files changed

+122
-15
lines changed

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description = "Spring for GraphQL"
33
ext {
44
moduleProjects = [project(":spring-graphql"), project(":spring-graphql-test")]
55
springFrameworkVersion = "6.1.11"
6-
graphQlJavaVersion = "22.1"
6+
graphQlJavaVersion = "22.2"
77
springBootVersion = "3.3.0"
88
}
99

spring-graphql-docs/modules/ROOT/pages/request-execution.adoc

+11-14
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,7 @@ and `DataFetcherExceptionResolver` and `SubscriptionExceptionResolver` beans fo
2828
xref:request-execution.adoc#execution.exceptions[exception resolution]. For further customizations, you can also
2929
declare a `GraphQlSourceBuilderCustomizer` bean, for example:
3030

31-
[source,java,indent=0,subs="verbatim,quotes"]
32-
----
33-
@Configuration(proxyBeanMethods = false)
34-
class GraphQlConfig {
35-
36-
@Bean
37-
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
38-
return (builder) ->
39-
builder.configureGraphQl(graphQlBuilder ->
40-
graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
41-
}
42-
}
43-
----
31+
include-code::GraphQlConfig[]
4432

4533

4634

@@ -409,7 +397,7 @@ request is simple enough and did not require asynchronous data fetching.
409397

410398

411399

412-
[[execution.reactive-datafetcher]]
400+
[[execution.reactivedatafetcher]]
413401
== Reactive `DataFetcher`
414402

415403
The default `GraphQlSource` builder enables support for a `DataFetcher` to return `Mono`
@@ -422,6 +410,15 @@ A reactive `DataFetcher` can rely on access to Reactor context propagated from t
422410
transport layer, such as from a WebFlux request handling, see
423411
xref:request-execution.adoc#execution.context.webflux[WebFlux Context].
424412

413+
In the case of subscription requests, GraphQL Java will produce items as soon as they
414+
are available and all their requested fields were fetched. Because this involves several
415+
layers of asynchronous data fetching, items might be sent over the wire out of their
416+
original order. If you wish GraphQL Java to buffer items and retain the original order,
417+
you can do so by setting the `SubscriptionExecutionStrategy.KEEP_SUBSCRIPTION_EVENTS_ORDERED`
418+
configuration flag in the `GraphQLContext`. This can be done, for example, with a custom
419+
`Instrumentation`:
420+
421+
include-code::GraphQlConfig[]
425422

426423

427424
[[execution.context]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2020-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.docs.execution.graphqlsource;
18+
19+
import graphql.execution.ExecutionId;
20+
import graphql.execution.ExecutionIdProvider;
21+
22+
class CustomExecutionIdProvider implements ExecutionIdProvider {
23+
@Override
24+
public ExecutionId provide(String query, String operationName, Object context) {
25+
return null;
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.docs.execution.graphqlsource;
18+
19+
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
20+
import org.springframework.context.annotation.Bean;
21+
import org.springframework.context.annotation.Configuration;
22+
23+
@Configuration(proxyBeanMethods = false)
24+
public class GraphQlConfig {
25+
26+
@Bean
27+
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
28+
return (builder) ->
29+
builder.configureGraphQl((graphQlBuilder) ->
30+
graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
31+
}
32+
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2020-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.docs.execution.reactivedatafetcher;
18+
19+
import graphql.ExecutionResult;
20+
import graphql.execution.SubscriptionExecutionStrategy;
21+
import graphql.execution.instrumentation.InstrumentationContext;
22+
import graphql.execution.instrumentation.InstrumentationState;
23+
import graphql.execution.instrumentation.SimpleInstrumentationContext;
24+
import graphql.execution.instrumentation.SimplePerformantInstrumentation;
25+
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
26+
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
30+
@Configuration(proxyBeanMethods = false)
31+
public class GraphQlConfig {
32+
33+
@Bean
34+
public SubscriptionOrderInstrumentation subscriptionOrderInstrumentation() {
35+
return new SubscriptionOrderInstrumentation();
36+
}
37+
38+
static class SubscriptionOrderInstrumentation extends SimplePerformantInstrumentation {
39+
40+
@Override
41+
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters,
42+
InstrumentationState state) {
43+
// Enable option for keeping subscription results in upstream order
44+
parameters.getGraphQLContext().put(SubscriptionExecutionStrategy.KEEP_SUBSCRIPTION_EVENTS_ORDERED, true);
45+
return SimpleInstrumentationContext.noOp();
46+
}
47+
48+
}
49+
50+
}

0 commit comments

Comments
 (0)