Skip to content

Commit 1cd6e03

Browse files
authored
fix: enable spring subscription callback module using RC version (#397)
1 parent 3efd208 commit 1cd6e03

File tree

7 files changed

+34
-55
lines changed

7 files changed

+34
-55
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ graphQLJavaVersion = 22.0
77
mockWebServerVersion = 4.12.0
88
protobufVersion = 4.26.1
99
slf4jVersion = 2.0.13
10-
springBootVersion = 3.2.5
11-
springGraphQLVersion = 1.2.6
10+
springBootVersion = 3.3.0-RC1
11+
springGraphQLVersion = 1.3.0-RC1
1212
reactorVersion = 3.6.6
1313

1414
# test dependencies

graphql-java-support/src/main/java/com/apollographql/federation/graphqljava/caching/CacheControlInstrumentation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
* A GraphQL Java Instrumentation that computes a max age for an operation based on @cacheControl
1919
* directives.
2020
*
21-
* By default, this instrumentation will only set the `Cache-Control` `max-age` value IF positive int
22-
* value is provided. If you would rather want to return explicit `max-age=0` values, you need to
23-
* explicitly opt-in to this behavior by specifying `allowZeroMaxAge=true` constructor value.
21+
* <p>By default, this instrumentation will only set the `Cache-Control` `max-age` value IF positive
22+
* int value is provided. If you would rather want to return explicit `max-age=0` values, you need
23+
* to explicitly opt-in to this behavior by specifying `allowZeroMaxAge=true` constructor value.
2424
*
2525
* <p>You can retrieve the "max-age=..." header value with a {@link GraphQLContext}: <code>
2626
* String cacheControlHeader = CacheControlInstrumentation.cacheControlContext(context);

settings.gradle.kts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
rootProject.name = "federation-jvm"
22

33
include(":federation-graphql-java-support")
4-
// TODO: disabling spring-subscription-callback module until Spring Boot 3.3 is released
5-
//include(":federation-spring-subscription-callback")
4+
include(":federation-spring-subscription-callback")
65

76
project(":federation-graphql-java-support").projectDir = file("graphql-java-support")
8-
// TODO: disabling spring-subscription-callback module until Spring Boot 3.3 is released
9-
//project(":federation-spring-subscription-callback").projectDir = file("spring-subscription-callback")
7+
project(":federation-spring-subscription-callback").projectDir = file("spring-subscription-callback")

spring-subscription-callback/build.gradle.kts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ plugins {
44
id("com.apollographql.federation.java-conventions")
55
}
66

7+
repositories {
8+
mavenCentral()
9+
maven {
10+
url = uri("https://repo.spring.io/milestone")
11+
}
12+
}
13+
714
val annotationsVersion: String by project
815
val graphQLJavaVersion: String by project
916
val mockWebServerVersion: String by project
@@ -27,7 +34,6 @@ dependencies {
2734
testImplementation("org.springframework.boot", "spring-boot-starter-websocket", springBootVersion)
2835
testImplementation("org.springframework.graphql", "spring-graphql-test", springGraphQLVersion)
2936
testImplementation("io.projectreactor", "reactor-test", reactorVersion)
30-
3137
}
3238

3339
java {

spring-subscription-callback/src/main/java/com/apollographql/subscription/webflux/CallbackGraphQlHttpHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public Mono<ServerResponse> handleRequest(@NotNull ServerRequest serverRequest)
6969
serverRequest.uri(),
7070
serverRequest.headers().asHttpHeaders(),
7171
serverRequest.cookies(),
72+
serverRequest.remoteAddress().orElse(null),
7273
serverRequest.attributes(),
7374
body,
7475
serverRequest.exchange().getRequest().getId(),

spring-subscription-callback/src/main/java/com/apollographql/subscription/webmvc/CallbackGraphQlHttpHandler.java

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import com.apollographql.subscription.callback.SubscriptionCallbackHandler;
88
import graphql.ExecutionResult;
99
import jakarta.servlet.ServletException;
10-
import jakarta.servlet.http.Cookie;
11-
import java.io.IOException;
1210
import java.util.Arrays;
1311
import java.util.List;
1412
import java.util.Map;
@@ -20,13 +18,9 @@
2018
import org.springframework.graphql.server.WebGraphQlHandler;
2119
import org.springframework.graphql.server.WebGraphQlRequest;
2220
import org.springframework.graphql.server.webmvc.GraphQlHttpHandler;
23-
import org.springframework.http.HttpCookie;
2421
import org.springframework.http.MediaType;
2522
import org.springframework.util.AlternativeJdkIdGenerator;
2623
import org.springframework.util.IdGenerator;
27-
import org.springframework.util.LinkedMultiValueMap;
28-
import org.springframework.util.MultiValueMap;
29-
import org.springframework.web.server.ServerWebInputException;
3024
import org.springframework.web.servlet.function.ServerRequest;
3125
import org.springframework.web.servlet.function.ServerResponse;
3226
import reactor.core.publisher.Mono;
@@ -79,6 +73,7 @@ public CallbackGraphQlHttpHandler(
7973
serverRequest.uri(),
8074
serverRequest.headers().asHttpHeaders(),
8175
initCookies(serverRequest),
76+
serverRequest.remoteAddress().orElse(null),
8277
serverRequest.attributes(),
8378
readBody(serverRequest),
8479
this.idGenerator.generateId().toString(),
@@ -145,29 +140,6 @@ public CallbackGraphQlHttpHandler(
145140
}
146141
}
147142

148-
private static MultiValueMap<String, HttpCookie> initCookies(ServerRequest serverRequest) {
149-
MultiValueMap<String, Cookie> source = serverRequest.cookies();
150-
MultiValueMap<String, HttpCookie> target = new LinkedMultiValueMap<>(source.size());
151-
source
152-
.values()
153-
.forEach(
154-
cookieList ->
155-
cookieList.forEach(
156-
cookie -> {
157-
HttpCookie httpCookie = new HttpCookie(cookie.getName(), cookie.getValue());
158-
target.add(cookie.getName(), httpCookie);
159-
}));
160-
return target;
161-
}
162-
163-
private static Map<String, Object> readBody(ServerRequest request) throws ServletException {
164-
try {
165-
return request.body(MAP_PARAMETERIZED_TYPE_REF);
166-
} catch (IOException ex) {
167-
throw new ServerWebInputException("I/O error while reading request body", null, ex);
168-
}
169-
}
170-
171143
private static MediaType selectResponseMediaType(ServerRequest serverRequest) {
172144
for (MediaType accepted : serverRequest.headers().accept()) {
173145
if (SUPPORTED_MEDIA_TYPES.contains(accepted)) {

spring-subscription-callback/src/test/java/com/apollographql/subscription/callback/SubscriptionCallbackHandlerTest.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
import org.jetbrains.annotations.NotNull;
2626
import org.junit.jupiter.api.Assertions;
2727
import org.junit.jupiter.api.Test;
28+
import org.springframework.graphql.ExecutionGraphQlRequest;
29+
import org.springframework.graphql.ExecutionGraphQlResponse;
30+
import org.springframework.graphql.ExecutionGraphQlService;
2831
import org.springframework.graphql.server.WebGraphQlHandler;
2932
import org.springframework.graphql.server.WebGraphQlRequest;
3033
import org.springframework.graphql.server.WebGraphQlResponse;
31-
import org.springframework.graphql.server.WebSocketGraphQlInterceptor;
3234
import org.springframework.graphql.support.DefaultExecutionGraphQlResponse;
3335
import org.springframework.http.HttpHeaders;
3436
import org.springframework.http.HttpStatus;
@@ -39,21 +41,16 @@
3941

4042
public class SubscriptionCallbackHandlerTest {
4143

42-
static class MockWebHandler implements WebGraphQlHandler {
44+
static class MockExecutionEngine implements ExecutionGraphQlService {
4345

4446
private final Flux subscriptionFlux;
4547

46-
public MockWebHandler(Flux subscriptionFlux) {
48+
public MockExecutionEngine(Flux subscriptionFlux) {
4749
this.subscriptionFlux = subscriptionFlux;
4850
}
4951

5052
@Override
51-
public WebSocketGraphQlInterceptor getWebSocketInterceptor() {
52-
return null;
53-
}
54-
55-
@Override
56-
public @NotNull Mono<WebGraphQlResponse> handleRequest(@NotNull WebGraphQlRequest request) {
53+
public Mono<ExecutionGraphQlResponse> execute(ExecutionGraphQlRequest request) {
5754
var executionResult = ExecutionResult.newExecutionResult().data(subscriptionFlux).build();
5855
var executionResponse =
5956
new DefaultExecutionGraphQlResponse(request.toExecutionInput(), executionResult);
@@ -62,6 +59,10 @@ public WebSocketGraphQlInterceptor getWebSocketInterceptor() {
6259
}
6360
}
6461

62+
static WebGraphQlHandler mockHandler(Flux subscriptionFlux) {
63+
return WebGraphQlHandler.builder(new MockExecutionEngine(subscriptionFlux)).build();
64+
}
65+
6566
@Test
6667
public void init_successful() {
6768
var capturedRequests = new ArrayList<String>();
@@ -81,7 +82,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) {
8182
var data =
8283
Flux.just(1, 2)
8384
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
84-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
85+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
8586

8687
var subscriptionId = UUID.randomUUID().toString();
8788
var callbackUrl = server.url("/callback/" + subscriptionId).toString();
@@ -132,7 +133,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) {
132133
var data =
133134
Flux.just(1, 2)
134135
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
135-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
136+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
136137

137138
var subscriptionId = UUID.randomUUID().toString();
138139
var callbackUrl = server.url("/callback/" + subscriptionId).toString();
@@ -184,7 +185,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) {
184185
Flux.just(1, 2)
185186
.delayElements(Duration.ofMillis(3000))
186187
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
187-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
188+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
188189

189190
// note: heartbeat goes into infinite recursion and does not emit value
190191
// TODO update to use virtual timer
@@ -249,7 +250,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) {
249250
Flux.just(1, 2)
250251
.delayElements(Duration.ofMillis(3000))
251252
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
252-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
253+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
253254

254255
// note: heartbeat goes into infinite recursion and does not emit value
255256
// TODO update to use virtual timer
@@ -280,7 +281,7 @@ public void subscription_success() {
280281
Flux.just(1, 2)
281282
.delayElements(Duration.ofMillis(50))
282283
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
283-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
284+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
284285

285286
var subscriptionId = UUID.randomUUID().toString();
286287
var callbackUrl = server.url("/callback/" + subscriptionId).toString();
@@ -309,7 +310,7 @@ public void subscription_success_without_heartbeats() {
309310
Flux.just(1, 2)
310311
.delayElements(Duration.ofMillis(50))
311312
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build());
312-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
313+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
313314

314315
var subscriptionId = UUID.randomUUID().toString();
315316
var callbackUrl = server.url("/callback/" + subscriptionId).toString();
@@ -339,7 +340,7 @@ public void subscription_exception() {
339340
.delayElements(Duration.ofMillis(50))
340341
.map((i) -> ExecutionResult.newExecutionResult().data(Map.of("counter", i)).build())
341342
.concatWith(Mono.error(new RuntimeException("JUNIT_FAILURE")));
342-
var handler = new SubscriptionCallbackHandler(new MockWebHandler(data));
343+
var handler = new SubscriptionCallbackHandler(mockHandler(data));
343344

344345
var subscriptionId = UUID.randomUUID().toString();
345346
var callbackUrl = server.url("/callback/" + subscriptionId).toString();
@@ -385,6 +386,7 @@ private WebGraphQlRequest stubWebGraphQLRequest(String subscriptionId, String ca
385386
URI.create(callbackUrl),
386387
HttpHeaders.EMPTY,
387388
null,
389+
null,
388390
Collections.emptyMap(),
389391
createMockGraphQLRequest(subscriptionId, callbackUrl),
390392
UUID.randomUUID().toString(),

0 commit comments

Comments
 (0)