@@ -35,18 +35,18 @@ Spring for GraphQL requires the following as a baseline:
35
35
36
36
37
37
38
- [[web -transports]]
39
- == Web Transports
38
+ [[server -transports]]
39
+ == Server Transports
40
40
41
- Spring for GraphQL supports GraphQL requests over HTTP and over WebSocket.
41
+ Spring for GraphQL supports server handling of GraphQL requests over HTTP, WebSocket, and
42
+ RSocket.
42
43
43
44
44
-
45
- [[web-http]]
45
+ [[server-http]]
46
46
=== HTTP
47
47
48
48
`GraphQlHttpHandler` handles GraphQL over HTTP requests and delegates to the
49
- <<web -interception>> chain for request execution. There are two variants, one for
49
+ <<server -interception>> chain for request execution. There are two variants, one for
50
50
Spring MVC and one for Spring WebFlux. Both handle requests asynchronously and have
51
51
equivalent functionality, but rely on blocking vs non-blocking I/O respectively for
52
52
writing the HTTP response.
@@ -70,15 +70,15 @@ The Spring for GraphQL repository contains a Spring MVC
70
70
71
71
72
72
73
- [[web -websocket]]
73
+ [[server -websocket]]
74
74
=== WebSocket
75
75
76
76
`GraphQlWebSocketHandler` handles GraphQL over WebSocket requests based on the
77
77
https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md[protocol] defined in the
78
78
https://github.com/enisdenjo/graphql-ws[graphql-ws] library. The main reason to use
79
79
GraphQL over WebSocket is subscriptions which allow sending a stream of GraphQL
80
80
responses, but it can also be used for regular queries with a single response.
81
- The handler delegates every request to the <<web -interception>> chain for further
81
+ The handler delegates every request to the <<server -interception>> chain for further
82
82
request execution.
83
83
84
84
[TIP]
@@ -113,17 +113,52 @@ The Spring for GraphQL repository contains a WebFlux
113
113
114
114
115
115
116
- [[web-interception ]]
117
- === Web Interception
116
+ [[server-rsocket ]]
117
+ === RSocket
118
118
119
- <<web-http>> and <<web-websocket>> transport handlers delegate to a common Web
120
- interception chain for request execution. The chain consists of a sequence of
121
- `WebGraphQlInterceptor` components, followed by a `ExecutionGraphQlService` that
122
- invokes GraphQL Java.
119
+ `GraphQlRSocketHandler` handles GraphQL over RSocket requests. Queries and mutations are
120
+ expected and handled as an RSocket `request-response` interaction while subscriptions are
121
+ handled as `request-stream`.
123
122
124
- `WebGraphQlInterceptor` is as a common contract to use in both Spring MVC and
125
- WebFlux applications. Use it to intercept requests, inspect HTTP request headers, or to
126
- register a transformation of the `graphql.ExecutionInput`:
123
+ `GraphQlRSocketHandler` can be used a delegate from an `@Controller` that is mapped to
124
+ the route for GraphQL requests. For example:
125
+
126
+ [source,java,indent=0,subs="verbatim,quotes"]
127
+ ----
128
+ @Controller
129
+ public class GraphQlRSocketController {
130
+
131
+ private final GraphQlRSocketHandler handler;
132
+
133
+ GraphQlRSocketController(GraphQlRSocketHandler handler) {
134
+ this.handler = handler;
135
+ }
136
+
137
+ @MessageMapping("graphql")
138
+ public Mono<Map<String, Object>> handle(Map<String, Object> payload) {
139
+ return this.handler.handle(payload);
140
+ }
141
+
142
+ @MessageMapping("graphql")
143
+ public Flux<Map<String, Object>> handleSubscription(Map<String, Object> payload) {
144
+ return this.handler.handleSubscription(payload);
145
+ }
146
+ }
147
+ ----
148
+
149
+
150
+
151
+
152
+
153
+ [[server-interception]]
154
+ === Server Interception
155
+
156
+ GraphQL <<server-http>> and <<server-websocket>> handlers for Spring MVC and WebFlux
157
+ delegate to a common `WebGraphQlInterceptor` chain followed by an `ExecutionGraphQlService`
158
+ that invokes the GraphQL Java engine.
159
+
160
+ You can write an interceptor to check requests details or transform the
161
+ `graphql.ExecutionInput` for GraphQL Java:
127
162
128
163
[source,java,indent=0,subs="verbatim,quotes"]
129
164
----
@@ -140,8 +175,8 @@ class MyInterceptor implements WebGraphQlInterceptor {
140
175
}
141
176
----
142
177
143
- Use `WebGraphQlInterceptor` also to intercept responses, add HTTP response headers,
144
- or transform the `graphql.ExecutionResult`:
178
+ Interceptors can customize HTTP response headers, or inspect and/or transform the
179
+ `graphql.ExecutionResult` from GraphQL Java :
145
180
146
181
[source,java,indent=0,subs="verbatim,quotes"]
147
182
----
@@ -159,19 +194,22 @@ class MyInterceptor implements WebGraphQlInterceptor {
159
194
}
160
195
----
161
196
162
- `WebGraphQlHandler` provides a builder to initialize the Web interception chain. After
163
- you build the chain, you can use the resulting `WebGraphQlHandler` to initialize the HTTP
164
- or WebSocket transport handlers. The Boot starter configures all this, see the
165
- {spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints] section for
166
- details, or check `GraphQlWebMvcAutoConfiguration` or `GraphQlWebFluxAutoConfiguration`
167
- it contains, for the actual config.
197
+ `WebGraphQlHandler` has a builder to create the `WebGraphInterceptor` chain. The Boot
198
+ starter uses this, see Boot's section on
199
+ {spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints].
200
+
201
+ The <<server-rsocket>> handler delegates to a similar chain except
202
+ the interceptor type is `GraphQlInterceptor`. To use, create `GraphQlRSocketHandler` with
203
+ the list of interceptors to apply to requests.
204
+
205
+
168
206
169
207
170
208
[[execution]]
171
209
== Request Execution
172
210
173
211
`ExecutionGraphQlService` is the main Spring abstraction to call GraphQL Java to execute
174
- requests. Underlying transports, such as the <<web -transports>>, delegate to
212
+ requests. Underlying transports, such as the <<server -transports>>, delegate to
175
213
`ExecutionGraphQlService` to handle requests.
176
214
177
215
The main implementation, `DefaultExecutionGraphQlService`, is configured with a
@@ -212,10 +250,9 @@ class GraphQlConfig {
212
250
213
251
@Bean
214
252
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
215
- return (builder) -> {
216
- builder.configureGraphQl(graphQlBuilder ->
217
- graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
218
- };
253
+ return (builder) ->
254
+ builder.configureGraphQl(graphQlBuilder ->
255
+ graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
219
256
}
220
257
}
221
258
----
@@ -380,10 +417,10 @@ such beans, so you might have something like:
380
417
@Configuration
381
418
public class GraphQlConfig {
382
419
383
- @Bean
384
- public RuntimeWiringConfigurer runtimeWiringConfigurer() {
385
- return builder -> builder.directiveWiring(new MySchemaDirectiveWiring());
386
- }
420
+ @Bean
421
+ public RuntimeWiringConfigurer runtimeWiringConfigurer() {
422
+ return builder -> builder.directiveWiring(new MySchemaDirectiveWiring());
423
+ }
387
424
388
425
}
389
426
----
@@ -413,7 +450,7 @@ transport layer, such as from a WebFlux request handling, see
413
450
=== Context Propagation
414
451
415
452
Spring for GraphQL provides support to transparently propagate context from the
416
- <<web -transports>>, through GraphQL Java, and to `DataFetcher` and other components it
453
+ <<server -transports>>, through GraphQL Java, and to `DataFetcher` and other components it
417
454
invokes. This includes both `ThreadLocal` context from the Spring MVC request handling
418
455
thread and Reactor `Context` from the WebFlux processing pipeline.
419
456
@@ -423,7 +460,7 @@ thread and Reactor `Context` from the WebFlux processing pipeline.
423
460
424
461
A `DataFetcher` and other components invoked by GraphQL Java may not always execute on
425
462
the same thread as the Spring MVC handler, for example if an asynchronous
426
- <<web -interception, `WebGraphQlInterceptor`>> or `DataFetcher` switches to a
463
+ <<server -interception, `WebGraphQlInterceptor`>> or `DataFetcher` switches to a
427
464
different thread.
428
465
429
466
Spring for GraphQL supports propagating `ThreadLocal` values from the Servlet container
@@ -457,7 +494,7 @@ public class RequestAttributesAccessor implements ThreadLocalAccessor {
457
494
}
458
495
----
459
496
460
- A `ThreadLocalAccessor` can be registered in the <<web -interception,WebGraphHandler>>
497
+ A `ThreadLocalAccessor` can be registered in the <<server -interception,WebGraphHandler>>
461
498
builder. The Boot starter detects beans of this type and automatically registers them for
462
499
Spring MVC application, see the
463
500
{spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints] section.
@@ -468,7 +505,7 @@ Spring MVC application, see the
468
505
469
506
A <<execution-reactive-datafetcher>> can rely on access to Reactor context that
470
507
originates from the WebFlux request handling chain. This includes Reactor context
471
- added by <<web -interception, WebGraphQlInterceptor>> components.
508
+ added by <<server -interception, WebGraphQlInterceptor>> components.
472
509
473
510
474
511
@@ -546,11 +583,11 @@ public class MyConfig {
546
583
public MyConfig(BatchLoaderRegistry registry) {
547
584
548
585
registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
549
- // return Mono<Map<Long, Author>
550
- });
586
+ // return Mono<Map<Long, Author>
587
+ });
551
588
552
- // more registrations ...
553
- }
589
+ // more registrations ...
590
+ }
554
591
555
592
}
556
593
----
@@ -679,12 +716,12 @@ dependencies {
679
716
//...
680
717
681
718
annotationProcessor "com.querydsl:querydsl-apt:$querydslVersion:jpa",
682
- 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final',
683
- 'javax.annotation:javax.annotation-api:1.3.2'
719
+ 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final',
720
+ 'javax.annotation:javax.annotation-api:1.3.2'
684
721
}
685
722
686
723
compileJava {
687
- options.annotationProcessorPath = configurations.annotationProcessor
724
+ options.annotationProcessorPath = configurations.annotationProcessor
688
725
}
689
726
----
690
727
[source,xml,indent=0,subs="verbatim,quotes,attributes",role="secondary"]
@@ -1238,12 +1275,12 @@ Bean Validation lets you declare constraints on types, as the following example
1238
1275
----
1239
1276
public class BookInput {
1240
1277
1241
- @NotNull
1242
- private String title;
1278
+ @NotNull
1279
+ private String title;
1243
1280
1244
1281
@NotNull
1245
- @Size(max=13)
1246
- private String isbn;
1282
+ @Size(max=13)
1283
+ private String isbn;
1247
1284
}
1248
1285
----
1249
1286
@@ -1502,7 +1539,7 @@ Batch mapping methods can return:
1502
1539
[[security]]
1503
1540
== Security
1504
1541
1505
- The path to a <<web -transports, Web>> GraphQL endpoint can be secured with HTTP
1542
+ The path to a <<server -transports, Web>> GraphQL endpoint can be secured with HTTP
1506
1543
URL security to ensure that only authenticated users can access it. This does not,
1507
1544
however, differentiate among different GraphQL requests on such a shared endpoint on
1508
1545
a single URL.
0 commit comments