@@ -135,7 +135,7 @@ which is a strategy for loading the document for a request by file name.
135
135
136
136
Once you have a <<client-graphqlclient>>, you can begin to perform requests via
137
137
<<client-requests-retrieve, retrieve()>> or <<client-requests-execute, execute()>>
138
- where the former is merely a shortcut for the latter.
138
+ where the former is only a shortcut for the latter.
139
139
140
140
141
141
@@ -159,50 +159,42 @@ The below retrieves and decodes the data for a query:
159
159
.retrieve("project") <2>
160
160
.toEntity(Project.class); <3>
161
161
----
162
- <1> The operation to perform
163
- <2> Specify a path under the "data" key in the response map
164
- <3> Decode the data at the path to the target type
162
+ <1> The operation to perform.
163
+ <2> The path under the "data" key in the response map to decode from.
164
+ <3> Decode the data at the path to the target type.
165
165
166
- The document is a `String` that could be a literal or produced through a code generated
167
- request object. You can also define documents in files and use a
166
+ The input document is a `String` that could be a literal or produced through a code
167
+ generated request object. You can also define documents in files and use a
168
168
<<client-requests-document-source>> to resole them by file name.
169
169
170
170
The path is relative to the "data" key and uses a simple dot (".") separated notation
171
- for nested fields with optional array indices for list elements, e.g. `"project.name"`,
172
- `"project.releases[0].version"`, and so on .
171
+ for nested fields with optional array indices for list elements, e.g. `"project.name"`
172
+ or `"project.releases[0].version"`.
173
173
174
- Decoding can fail with `FieldAccessException` if the given path is not present in the
175
- response map, or when the value is `null` and there is an error for the field.
176
-
177
- By default, `FieldAccessException` is also raised on `retrieve` for partial data where
178
- the field value exists but nested fields may be `null` with a field error. In such
179
- cases, you can handle the exception to examine the errors and decide whether or how to
180
- decode the partial data:
174
+ Decoding can result in `FieldAccessException` if the given path is not present, or the
175
+ field value is `null` and has an error. `FieldAccessException` provides access to the
176
+ response and the field:
181
177
182
178
[source,java,indent=0,subs="verbatim,quotes"]
183
179
----
184
180
Mono<Project> projectMono = graphQlClient.document(document)
185
181
.retrieve("project")
186
182
.toEntity(Project.class)
187
183
.onErrorResume(FieldAccessException.class, ex -> {
188
- ResponseField field = ex.getField();
189
- // Use field to check nested field errors and/or decode
190
- // Return Mono with Project or an error
184
+ ClientGraphQlResponse response = ex.getResponse();
185
+ // ...
186
+ GraphQlResponseField field = ex.getField();
187
+ // ...
191
188
});
192
189
----
193
190
194
- TIP: The GraphQL spec considers a partial response or a partial field to be valid, and
195
- it may be feasible to decode them. By contrast, a failed field (i.e. value not present or
196
- is `null` with field error) or a failed response (no "data" key) are not valid and
197
- attempts to decode those are always rejected.
198
-
199
191
200
192
201
193
[[client-requests-execute]]
202
194
=== Execute
203
195
204
- The `retrieve` method is only a shortcut to decode from a single path to a higher level
205
- object. For more control and access to the response , use the `execute` method.
196
+ `retrieve` is only a shortcut to decode from a single path in the response map. For more
197
+ control, use the `execute` method and handle the response:
206
198
207
199
For example:
208
200
@@ -212,17 +204,27 @@ For example:
212
204
Mono<Project> projectMono = graphQlClient.document(document)
213
205
.execute()
214
206
.map(response -> {
215
- // Check response.isValid(), getErrors()
207
+ if (!response.isValid()) {
208
+ // Request failure... <1>
209
+ }
216
210
217
211
ResponseField field = response.field("project");
218
- // Check field.hasValue(), getError()
219
-
220
- return field.toEntity(Project.class)
212
+ if (!field.hasValue()) {
213
+ if (field.getError() != null) {
214
+ // Field failure... <2>
215
+ }
216
+ else {
217
+ // Optional field set to null... <3>
218
+ }
219
+ }
220
+
221
+ return field.toEntity(Project.class); <4>
221
222
});
222
223
----
223
-
224
- You can use `execute` to check response errors, obtain different fields, check their
225
- field errors and nested field errors, and/or decode their values.
224
+ <1> The response does not have data, only errors
225
+ <2> Field that is `null` and has an associated error
226
+ <3> Field that was set to `null` by its `DataFetcher`
227
+ <4> Decode the data at the given path
226
228
227
229
228
230
@@ -272,7 +274,7 @@ You can use the `GraphQlClient` <<client-graphqlclient-builder>> to customize th
272
274
== Subscriptions
273
275
274
276
For a subscription operation, call `retrieveSubscription` instead of `retrieve` to
275
- obtain a stream of responses rather than a single response :
277
+ obtain a stream of responses, each decoded to a target object :
276
278
277
279
[source,java,indent=0,subs="verbatim,quotes"]
278
280
----
@@ -281,29 +283,34 @@ obtain a stream of responses rather than a single response:
281
283
.toEntity(String.class);
282
284
----
283
285
284
- Similar to the <<client-requests-retrieve>> vs <<client-requests-execute>> choice
285
- for requests with a single response, the same choice is also available for subscriptions.
286
- For example, for more control over each response, use `executeSubscription` instead of
287
- `retrieveSubscription`:
286
+ Similar to the <<client-requests-retrieve, retrieve>> vs <<client-requests-execute, execute>>
287
+ alternatives for single response requests, the same is also available for subscriptions.
288
+ For more control over each response, use `executeSubscription`:
288
289
289
290
[source,java,indent=0,subs="verbatim,quotes"]
290
291
----
291
292
Flux<String> greetingFlux = client.document("subscription { greetings }")
292
293
.executeSubscription()
293
294
.map(response -> {
294
- // Check response.isValid(), getErrors()
295
+ if (!response.isValid()) {
296
+ // Request failure...
297
+ }
295
298
296
- ResponseField field = response.field("greeting");
297
- // Check field.isValid(), getError()
299
+ ResponseField field = response.field("project");
300
+ if (!field.hasValue()) {
301
+ if (field.getError() != null) {
302
+ // Field failure...
303
+ }
304
+ else {
305
+ // Optional field set to null... <3>
306
+ }
307
+ }
298
308
299
309
return field.toEntity(String.class)
300
310
});
301
311
----
302
312
303
-
304
-
305
- Subscriptions are supported only with the <<client-websocketgraphqlclient,
306
- WebSocketGraphQlClient>> extension.
313
+ NOTE: Subscriptions are supported only over <<client-websocketgraphqlclient, WebSocket>>.
307
314
308
315
309
316
0 commit comments