Skip to content

Commit 87aa98b

Browse files
committed
Update docs for synchronous GraphQlClient
Closes gh-771
1 parent 08d831a commit 87aa98b

File tree

1 file changed

+153
-20
lines changed

1 file changed

+153
-20
lines changed

spring-graphql-docs/modules/ROOT/pages/client.adoc

Lines changed: 153 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,77 @@
11
[[client]]
22
= Client
33

4-
Spring for GraphQL includes client support for executing GraphQL requests over HTTP,
4+
Spring for GraphQL includes client support to execute GraphQL requests over HTTP,
55
WebSocket, and RSocket.
66

77

88

99
[[client.graphqlclient]]
1010
== `GraphQlClient`
1111

12-
`GraphQlClient` is a contract that declares a common workflow for GraphQL requests that is
13-
independent of the underlying transport. That means requests are executed with the same API
14-
no matter what the underlying transport, and anything transport specific is configured at
15-
build time.
12+
`GraphQlClient` defines a common workflow for GraphQL requests independent of the underlying
13+
transport, so the way you perform requests is the same no matter what transport is in use.
1614

17-
To create a `GraphQlClient` you need one of the following extensions:
15+
The following transport specific `GraphQlClient` extensions are available:
1816

17+
- xref:client.adoc#client.httpsyncgraphqlclient[HttpSyncGraphQlClient]
1918
- xref:client.adoc#client.httpgraphqlclient[HttpGraphQlClient]
2019
- xref:client.adoc#client.websocketgraphqlclient[WebSocketGraphQlClient]
2120
- xref:client.adoc#client.rsocketgraphqlclient[RSocketGraphQlClient]
2221

2322
Each defines a `Builder` with options relevant to the transport. All builders extend
24-
from a common, base GraphQlClient xref:client.adoc#client.graphqlclient.builder[`Builder`] with options
25-
relevant to all extensions.
23+
from a common, base GraphQlClient xref:client.adoc#client.graphqlclient.builder[`Builder`]
24+
with options applicable to all transports.
25+
26+
Once `GraphQlClient` is built you can begin to make xref:client.adoc#client.requests[requests].
27+
28+
29+
[[client.httpsyncgraphqlclient]]
30+
=== HTTP Sync
31+
32+
`HttpSyncGraphQlClient` uses
33+
{spring-framework-ref-docs}/integration/rest-clients.html#rest-restclient[RestClient]
34+
to execute GraphQL requests over HTTP through a blocking transport contract and chain of
35+
interceptors.
36+
37+
[source,java,indent=0,subs="verbatim,quotes"]
38+
----
39+
RestClient restClient = ... ;
40+
HttpSyncGraphQlClient graphQlClient = HttpSyncGraphQlClient.create(restClient);
41+
----
42+
43+
Once `HttpSyncGraphQlClient` is created, you can begin to
44+
xref:client.adoc#client.requests[execute requests] using the same API, independent of the underlying
45+
transport. If you need to change any transport specific details, use `mutate()` on an
46+
existing `HttpSyncGraphQlClient` to create a new instance with customized settings:
47+
48+
[source,java,indent=0,subs="verbatim,quotes"]
49+
----
50+
RestClient restClient = ... ;
51+
52+
HttpSyncGraphQlClient graphQlClient = HttpSyncGraphQlClient.builder(restClient)
53+
.headers(headers -> headers.setBasicAuth("joe", "..."))
54+
.build();
55+
56+
// Perform requests with graphQlClient...
57+
58+
HttpSyncGraphQlClient anotherGraphQlClient = graphQlClient.mutate()
59+
.headers(headers -> headers.setBasicAuth("peter", "..."))
60+
.build();
61+
62+
// Perform requests with anotherGraphQlClient...
63+
64+
----
2665

27-
Once you have a `GraphQlClient` you can begin to make xref:client.adoc#client.requests[requests].
2866

2967

3068
[[client.httpgraphqlclient]]
3169
=== HTTP
3270

3371
`HttpGraphQlClient` uses
3472
{spring-framework-ref-docs}/web/webflux-webclient.html[WebClient] to execute
35-
GraphQL requests over HTTP.
73+
GraphQL requests over HTTP through a non-blocking transport contract and chain of
74+
interceptors.
3675

3776
[source,java,indent=0,subs="verbatim,quotes"]
3877
----
@@ -195,21 +234,25 @@ transport.
195234
[[client.graphqlclient.builder]]
196235
=== Builder
197236

198-
`GraphQlClient` defines a parent `Builder` with common configuration options for the
237+
`GraphQlClient` defines a parent `BaseBuilder` with common configuration options for the
199238
builders of all extensions. Currently, it has lets you configure:
200239

201240
- `DocumentSource` strategy to load the document for a request from a file
202241
- xref:client.adoc#client.interception[Interception] of executed requests
203242

243+
`BaseBuilder` is further extended by the following:
244+
245+
- `SyncBuilder` - blocking execution stack with a chain of ``SyncGraphQlInterceptor``'s.
246+
- `Builder` - non-blocking execution stack with chain of ``GraphQlInterceptor``'s.
204247

205248

206249

207250
[[client.requests]]
208251
== Requests
209252

210253
Once you have a xref:client.adoc#client.graphqlclient[`GraphQlClient`], you can begin to perform requests via
211-
xref:client.adoc#client.requests.retrieve[retrieve()] or xref:client.adoc#client.requests.execute[execute()]
212-
where the former is only a shortcut for the latter.
254+
xref:client.adoc#client.requests.retrieve[retrieve] or xref:client.adoc#client.requests.execute[execute]
255+
methods.
213256

214257

215258

@@ -218,7 +261,29 @@ where the former is only a shortcut for the latter.
218261

219262
The below retrieves and decodes the data for a query:
220263

221-
[source,java,indent=0,subs="verbatim,quotes"]
264+
[tabs]
265+
======
266+
Sync::
267+
+
268+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
269+
----
270+
String document = "{" +
271+
" project(slug:\"spring-framework\") {" +
272+
" name" +
273+
" releases {" +
274+
" version" +
275+
" }"+
276+
" }" +
277+
"}";
278+
279+
Project project = graphQlClient.document(document) <1>
280+
.retrieveSync("project") <2>
281+
.toEntity(Project.class); <3>
282+
----
283+
284+
Non-Blocking::
285+
+
286+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
222287
----
223288
String document = "{" +
224289
" project(slug:\"spring-framework\") {" +
@@ -233,6 +298,8 @@ The below retrieves and decodes the data for a query:
233298
.retrieve("project") <2>
234299
.toEntity(Project.class); <3>
235300
----
301+
======
302+
236303
<1> The operation to perform.
237304
<2> The path under the "data" key in the response map to decode from.
238305
<3> Decode the data at the path to the target type.
@@ -249,7 +316,28 @@ Decoding can result in `FieldAccessException` if the given path is not present,
249316
field value is `null` and has an error. `FieldAccessException` provides access to the
250317
response and the field:
251318

252-
[source,java,indent=0,subs="verbatim,quotes"]
319+
[tabs]
320+
======
321+
Sync::
322+
+
323+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
324+
----
325+
try {
326+
Project project = graphQlClient.document(document)
327+
.retrieveSync("project")
328+
.toEntity(Project.class);
329+
}
330+
catch (FieldAccessException ex) {
331+
ClientGraphQlResponse response = ex.getResponse();
332+
// ...
333+
ClientResponseField field = ex.getField();
334+
// ...
335+
}
336+
----
337+
338+
Non-Blocking::
339+
+
340+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
253341
----
254342
Mono<Project> projectMono = graphQlClient.document(document)
255343
.retrieve("project")
@@ -261,6 +349,7 @@ response and the field:
261349
// ...
262350
});
263351
----
352+
======
264353

265354

266355

@@ -272,9 +361,35 @@ response map. For more control, use the `execute` method and handle the response
272361

273362
For example:
274363

275-
[source,java,indent=0,subs="verbatim,quotes"]
364+
[tabs]
365+
======
366+
Sync::
367+
+
368+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
369+
----
370+
ClientGraphQlResponse response = graphQlClient.document(document).executeSync();
371+
372+
if (!response.isValid()) {
373+
// Request failure... <1>
374+
}
375+
376+
ClientResponseField field = response.field("project");
377+
if (!field.hasValue()) {
378+
if (field.getError() != null) {
379+
// Field failure... <2>
380+
}
381+
else {
382+
// Optional field set to null... <3>
383+
}
384+
}
385+
386+
Project project = field.toEntity(Project.class); <4>
276387
----
277388
389+
Non-Blocking::
390+
+
391+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
392+
----
278393
Mono<Project> projectMono = graphQlClient.document(document)
279394
.execute()
280395
.map(response -> {
@@ -295,6 +410,8 @@ For example:
295410
return field.toEntity(Project.class); <4>
296411
});
297412
----
413+
======
414+
298415
<1> The response does not have data, only errors
299416
<2> Field that is `null` and has an associated error
300417
<3> Field that was set to `null` by its `DataFetcher`
@@ -331,9 +448,9 @@ You can then:
331448

332449
[source,java,indent=0,subs="verbatim,quotes"]
333450
----
334-
Mono<Project> projectMono = graphQlClient.documentName("projectReleases") <1>
451+
Project project = graphQlClient.documentName("projectReleases") <1>
335452
.variable("slug", "spring-framework") <2>
336-
.retrieve()
453+
.retrieveSync()
337454
.toEntity(Project.class);
338455
----
339456
<1> Load the document from "projectReleases.graphql"
@@ -423,7 +540,23 @@ response directly:
423540
[[client.interception]]
424541
== Interception
425542

426-
You create a `GraphQlClientInterceptor` to intercept all requests through a client:
543+
For blocking transports created with the `GraphQlClient.SyncBuilder`, you create a
544+
`SyncGraphQlClientInterceptor` to intercept all requests through the client:
545+
546+
[source,java,indent=0,subs="verbatim,quotes"]
547+
----
548+
static class MyInterceptor implements SyncGraphQlClientInterceptor {
549+
550+
@Override
551+
public ClientGraphQlResponse intercept(ClientGraphQlRequest request, Chain chain) {
552+
// ...
553+
return chain.next(request);
554+
}
555+
}
556+
----
557+
558+
For non-blocking transports created with `GraphQlClient.Builder`, you create a
559+
`GraphQlClientInterceptor` to intercept all requests through the client:
427560

428561
[source,java,indent=0,subs="verbatim,quotes"]
429562
----
@@ -444,7 +577,7 @@ static class MyInterceptor implements GraphQlClientInterceptor {
444577
}
445578
----
446579

447-
Once the interceptor is created, register it through the client builder:
580+
Once the interceptor is created, register it through the client builder. For example:
448581

449582
[source,java,indent=0,subs="verbatim,quotes"]
450583
----

0 commit comments

Comments
 (0)