44
44
import com .fasterxml .jackson .databind .ObjectMapper ;
45
45
import com .introproventures .graphql .jpa .query .schema .GraphQLExecutor ;
46
46
import com .introproventures .graphql .jpa .query .schema .impl .GraphQLJpaExecutor ;
47
-
48
47
import graphql .DeferredExecutionResult ;
49
48
import graphql .ExecutionResult ;
50
49
import graphql .GraphQL ;
56
55
*
57
56
*/
58
57
@ RestController
59
- @ Transactional ( readOnly = true )
58
+ @ Transactional
60
59
public class GraphQLController {
61
60
62
61
private static final String PATH = "${spring.graphql.jpa.query.path:/graphql}" ;
@@ -76,7 +75,7 @@ public GraphQLController(GraphQLExecutor graphQLExecutor, ObjectMapper mapper) {
76
75
this .graphQLExecutor = graphQLExecutor ;
77
76
this .mapper = mapper ;
78
77
}
79
-
78
+
80
79
@ GetMapping (value = PATH ,
81
80
consumes = MediaType .TEXT_EVENT_STREAM_VALUE ,
82
81
produces = MediaType .TEXT_EVENT_STREAM_VALUE )
@@ -85,18 +84,18 @@ public SseEmitter getEventStream(@RequestParam(name = "query") final String quer
85
84
Map <String , Object > variablesMap = variablesStringToMap (variables );
86
85
87
86
ExecutionResult executionResult = graphQLExecutor .execute (query , variablesMap );
88
-
87
+
89
88
SseEmitter sseEmitter = new SseEmitter (180_000L ); // FIXME need to add parameter
90
89
sseEmitter .onTimeout (sseEmitter ::complete );
91
-
90
+
92
91
if (!executionResult .getErrors ().isEmpty ()) {
93
92
sseEmitter .send (executionResult .toSpecification (), MediaType .APPLICATION_JSON );
94
93
sseEmitter .completeWithError (new RuntimeException (executionResult .getErrors ().toString ()));
95
94
return sseEmitter ;
96
95
}
97
-
98
- Publisher <ExecutionResult > deferredResults = executionResult .getData ();
99
-
96
+
97
+ Publisher <ExecutionResult > deferredResults = executionResult .getData ();
98
+
100
99
// now send each deferred part which is given to us as a reactive stream
101
100
// of deferred values
102
101
deferredResults .subscribe (new Subscriber <ExecutionResult >() {
@@ -115,7 +114,7 @@ public void onNext(ExecutionResult executionResult) {
115
114
116
115
try {
117
116
SseEventBuilder event = wrap (executionResult );
118
-
117
+
119
118
sseEmitter .send (event );
120
119
} catch (IOException e ) {
121
120
sseEmitter .completeWithError (e );
@@ -131,21 +130,21 @@ public void onError(Throwable t) {
131
130
public void onComplete () {
132
131
sseEmitter .complete ();
133
132
}
134
-
133
+
135
134
SseEventBuilder wrap (ExecutionResult executionResult ) {
136
135
Map <String , Object > result = executionResult .getData ();
137
136
String name = result .keySet ().iterator ().next ();
138
-
137
+
139
138
return SseEmitter .event ()
140
139
.id ((id ++).toString ())
141
140
.name (name )
142
141
.data (result , MediaType .APPLICATION_JSON );
143
-
142
+
144
143
}
145
- });
146
-
144
+ });
145
+
147
146
return sseEmitter ;
148
- }
147
+ }
149
148
150
149
/**
151
150
* Handle standard GraphQL POST request that consumes
@@ -191,11 +190,11 @@ public void postJson(@RequestBody @Valid final GraphQLQueryRequest queryRequest,
191
190
public void getQuery (@ RequestParam (name = "query" ) final String query ,
192
191
@ RequestParam (name = "variables" , required = false ) final String variables ,
193
192
HttpServletResponse httpServletResponse ) throws IOException {
194
-
193
+
195
194
Map <String , Object > variablesMap = variablesStringToMap (variables );
196
195
197
196
ExecutionResult executionResult = graphQLExecutor .execute (query , variablesMap );
198
-
197
+
199
198
sendResponse (httpServletResponse , executionResult );
200
199
}
201
200
@@ -220,7 +219,7 @@ public void postForm(@RequestParam(name = "query") final String query,
220
219
Map <String , Object > variablesMap = variablesStringToMap (variables );
221
220
222
221
ExecutionResult executionResult = graphQLExecutor .execute (query , variablesMap );
223
-
222
+
224
223
sendResponse (httpServletResponse , executionResult );
225
224
}
226
225
@@ -312,11 +311,11 @@ public void setVariables(Map<String, Object> variables) {
312
311
}
313
312
314
313
}
315
-
314
+
316
315
private void sendResponse (HttpServletResponse response , ExecutionResult executionResult ) throws IOException {
317
316
if (hasDeferredResults (executionResult )) {
318
317
sendDeferredResponse (response , executionResult , executionResult .getExtensions ());
319
- }
318
+ }
320
319
else if (hasPublisherResults (executionResult )) {
321
320
sendMultipartResponse (response , executionResult , executionResult .getData ());
322
321
} else {
@@ -328,8 +327,8 @@ private void sendNormalResponse(HttpServletResponse response, ExecutionResult ex
328
327
response .setContentType ("application/json" );
329
328
response .setStatus (HttpServletResponse .SC_OK );
330
329
mapper .writeValue (response .getOutputStream (), executionResult .toSpecification ());
331
- }
332
-
330
+ }
331
+
333
332
private boolean hasDeferredResults (ExecutionResult executionResult ) {
334
333
return Optional .ofNullable (executionResult .getExtensions ())
335
334
.map (it -> it .containsKey (GraphQL .DEFERRED_RESULTS ))
@@ -339,12 +338,12 @@ private boolean hasDeferredResults(ExecutionResult executionResult) {
339
338
private boolean hasPublisherResults (ExecutionResult executionResult ) {
340
339
return Publisher .class .isInstance (executionResult .getData ());
341
340
}
342
-
341
+
343
342
private static final String CRLF = "\r \n " ;
344
343
345
344
@ SuppressWarnings ("unchecked" )
346
- private void sendDeferredResponse (HttpServletResponse response ,
347
- ExecutionResult executionResult ,
345
+ private void sendDeferredResponse (HttpServletResponse response ,
346
+ ExecutionResult executionResult ,
348
347
Map <Object , Object > extensions ) {
349
348
Publisher <DeferredExecutionResult > deferredResults = (Publisher <DeferredExecutionResult >) extensions .get (GraphQL .DEFERRED_RESULTS );
350
349
try {
@@ -354,8 +353,8 @@ private void sendDeferredResponse(HttpServletResponse response,
354
353
}
355
354
}
356
355
357
- private void sendMultipartResponse (HttpServletResponse response ,
358
- ExecutionResult executionResult ,
356
+ private void sendMultipartResponse (HttpServletResponse response ,
357
+ ExecutionResult executionResult ,
359
358
Publisher <? extends ExecutionResult > deferredResults ) {
360
359
// this implements this Apollo defer spec: https://github.com/apollographql/apollo-server/blob/defer-support/docs/source/defer-support.md
361
360
// the spec says CRLF + "-----" + CRLF is needed at the end, but it works without it and with it we get client
@@ -445,6 +444,6 @@ private String bodyToString() {
445
444
throw new RuntimeException (e );
446
445
}
447
446
}
448
- }
447
+ }
449
448
450
449
}
0 commit comments