13
13
import org .slf4j .Logger ;
14
14
import org .slf4j .LoggerFactory ;
15
15
import org .springframework .beans .factory .annotation .Autowired ;
16
+ import org .springframework .core .io .buffer .DataBuffer ;
17
+ import org .springframework .core .io .buffer .DataBufferFactory ;
18
+ import org .springframework .core .io .buffer .DefaultDataBufferFactory ;
19
+ import org .springframework .http .HttpHeaders ;
20
+ import org .springframework .http .HttpStatus ;
16
21
import org .springframework .http .MediaType ;
22
+ import org .springframework .http .server .reactive .ServerHttpResponse ;
17
23
import org .springframework .web .bind .annotation .CrossOrigin ;
18
24
import org .springframework .web .bind .annotation .RequestBody ;
19
25
import org .springframework .web .bind .annotation .RequestMapping ;
20
26
import org .springframework .web .bind .annotation .RequestMethod ;
21
27
import org .springframework .web .bind .annotation .RestController ;
28
+ import reactor .core .publisher .Flux ;
29
+ import reactor .core .publisher .Mono ;
22
30
23
- import javax .servlet .AsyncContext ;
24
- import javax .servlet .http .HttpServletRequest ;
25
- import javax .servlet .http .HttpServletResponse ;
26
31
import java .io .IOException ;
27
- import java .io . PrintWriter ;
32
+ import java .nio . charset . StandardCharsets ;
28
33
import java .util .LinkedHashMap ;
29
34
import java .util .Map ;
30
35
@@ -45,14 +50,14 @@ public class GraphQLController {
45
50
46
51
@ RequestMapping (value = "/test" , method = RequestMethod .GET , produces = MediaType .APPLICATION_JSON_VALUE )
47
52
@ CrossOrigin
48
- public void graphql (HttpServletRequest httpServletRequest , HttpServletResponse httpServletResponse ) throws IOException {
53
+ public Mono < Void > graphql (ServerHttpResponse serverHttpResponse ) throws IOException {
49
54
ImmutableMap <String , Object > body = ImmutableMap .of ("query" , "{books{title author comments @defer {user text}}}" );
50
- graphql (body , httpServletRequest , httpServletResponse );
55
+ return graphql (body , serverHttpResponse );
51
56
}
52
57
53
58
@ RequestMapping (value = "/graphql" , method = RequestMethod .POST , produces = MediaType .APPLICATION_JSON_VALUE )
54
59
@ CrossOrigin
55
- public void graphql (@ RequestBody Map <String , Object > body , HttpServletRequest httpServletRequest , HttpServletResponse httpServletResponse ) throws IOException {
60
+ public Mono < Void > graphql (@ RequestBody Map <String , Object > body , ServerHttpResponse serverHttpResponse ) throws IOException {
56
61
String query = (String ) body .get ("query" );
57
62
if (query == null ) {
58
63
query = "" ;
@@ -69,94 +74,163 @@ public void graphql(@RequestBody Map<String, Object> body, HttpServletRequest ht
69
74
ExecutionResult executionResult = graphql .execute (executionInput );
70
75
Map <Object , Object > extensions = executionResult .getExtensions ();
71
76
if (extensions != null && extensions .containsKey (GraphQL .DEFERRED_RESULTS )) {
72
- handleDeferResponse (httpServletRequest , httpServletResponse , executionResult , extensions );
77
+ return handleDeferResponse (serverHttpResponse , executionResult , extensions );
73
78
} else {
74
- handleNormalResponse (httpServletResponse , executionResult );
79
+ return handleNormalResponse (serverHttpResponse , executionResult );
75
80
}
76
81
}
77
82
78
- private void handleDeferResponse (HttpServletRequest httpServletRequest ,
79
- HttpServletResponse httpServletResponse ,
80
- ExecutionResult executionResult ,
81
- Map <Object , Object > extensions ) {
82
- AsyncContext asyncContext = httpServletRequest .startAsync ();
83
- asyncContext .start (() -> {
84
- Publisher <DeferredExecutionResult > deferredResults = (Publisher <DeferredExecutionResult >) extensions .get (GraphQL .DEFERRED_RESULTS );
85
- try {
86
- sendDeferResponse (asyncContext , httpServletRequest , httpServletResponse , executionResult , deferredResults );
87
- } catch (IOException e ) {
88
- e .printStackTrace ();
89
- }
90
- });
91
-
83
+ private Mono <Void > handleDeferResponse (ServerHttpResponse serverHttpResponse ,
84
+ ExecutionResult executionResult ,
85
+ Map <Object , Object > extensions ) {
86
+ Publisher <DeferredExecutionResult > deferredResults = (Publisher <DeferredExecutionResult >) extensions .get (GraphQL .DEFERRED_RESULTS );
87
+ try {
88
+ return sendDeferResponse (serverHttpResponse , executionResult , deferredResults );
89
+ } catch (Exception e ) {
90
+ e .printStackTrace ();
91
+ throw new RuntimeException (e );
92
+ }
92
93
}
93
94
94
- private void handleNormalResponse (HttpServletResponse httpServletResponse , ExecutionResult executionResult ) throws IOException {
95
+ private Mono < Void > handleNormalResponse (ServerHttpResponse serverHttpResponse , ExecutionResult executionResult ) throws IOException {
95
96
Map <String , Object > result = executionResult .toSpecification ();
96
- httpServletResponse .setStatus (HttpServletResponse .SC_OK );
97
- httpServletResponse .setCharacterEncoding ("UTF-8" );
98
- httpServletResponse .setContentType ("application/json" );
99
- httpServletResponse .setHeader ("Access-Control-Allow-Origin" , "*" );
97
+ serverHttpResponse .setStatusCode (HttpStatus .OK );
98
+ HttpHeaders headers = serverHttpResponse .getHeaders ();
99
+ headers .setContentType (MediaType .APPLICATION_JSON_UTF8 );
100
100
String body = objectMapper .writeValueAsString (result );
101
- PrintWriter writer = httpServletResponse .getWriter ();
102
- writer .write (body );
103
- writer .close ();
101
+ return serverHttpResponse .writeWith (strToDataBuffer (body ));
102
+ // PrintWriter writer = httpServletResponse.getWriter();
103
+ // writer.write(body);
104
+ // writer.close();
104
105
105
106
}
106
107
107
- private void sendDeferResponse (AsyncContext asyncContext , HttpServletRequest httpServletRequest , HttpServletResponse httpServletResponse , ExecutionResult executionResult , Publisher <DeferredExecutionResult > deferredResults ) throws IOException {
108
- httpServletResponse .setStatus (HttpServletResponse .SC_OK );
109
- httpServletResponse .setCharacterEncoding ("UTF-8" );
110
- httpServletResponse .setContentType ("multipart/mixed; boundary=\" -\" " );
111
- httpServletResponse .setHeader ("Access-Control-Allow-Origin" , "*" );
112
- httpServletResponse .setHeader ("Transfer-Encoding" , "chunked" );
113
- httpServletResponse .setHeader ("Connection" , "keep-alive" );
114
- PrintWriter writer = httpServletResponse .getWriter ();
108
+ private Mono <Void > sendDeferResponse (ServerHttpResponse serverHttpResponse , ExecutionResult executionResult , Publisher <DeferredExecutionResult > deferredResults ) {
109
+ serverHttpResponse .setStatusCode (HttpStatus .OK );
110
+ HttpHeaders headers = serverHttpResponse .getHeaders ();
111
+ headers .set ("Content-Type" , "multipart/mixed; boundary=\" -\" " );
112
+ headers .set ("transfer-encoding" , "chunked" );
113
+ // return message.headers().contains(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED, true);
114
+ headers .set ("Connection" , "keep-alive" );
115
115
116
- DeferPart deferPart = new DeferPart (executionResult .toSpecification ());
117
- writer .append (CRLF ).append ("---" ).append (CRLF );
118
- String body = deferPart .write ();
119
- writer .write (body );
120
- httpServletResponse .flushBuffer ();
121
116
122
- deferredResults . subscribe ( new Subscriber < DeferredExecutionResult >() {
117
+ DataBufferFactory dataBufferFactory = serverHttpResponse . bufferFactory ();
123
118
124
- Subscription subscription ;
125
119
126
- @ Override
127
- public void onSubscribe (Subscription s ) {
128
- subscription = s ;
129
- subscription .request (10 );
130
- }
120
+ // serverHttpResponse.writeAndFlushWith(Mono.just(firstDataBuffer)).subscribe(aVoid -> {
121
+ // System.out.println("done FIRST");
122
+ // }, throwable -> {
123
+ // throwable.printStackTrace();
124
+ // }, () -> {
125
+ // System.out.println("completed FIRST");
126
+ // });
127
+
128
+
129
+ // Flux<Mono<DataBuffer>> dataBufferFlux = Flux.from(deferredResults).map(deferredExecutionResult -> {
130
+ // DeferPart deferPart = new DeferPart(executionResult.toSpecification());
131
+ // StringBuilder builder = new StringBuilder();
132
+ // String body = deferPart.write();
133
+ // System.out.println("body:" + body);
134
+ // builder.append(CRLF).append("---").append(CRLF);
135
+ // builder.append(body);
136
+ // Mono<DataBuffer> dataBuffer = strToDataBuffer(dataBufferFactory, builder.toString());
137
+ // return dataBuffer;
138
+ // });
139
+
140
+ // Flux<Mono<DataBuffer>> resultFlux = Flux.mergeSequential(Flux.just(firstDataBuffer), dataBufferFlux);
141
+ // serverHttpResponse.writeAndFlushWith(resultFlux).subscribe(aVoid -> {
142
+ // StringBuilder end = new StringBuilder();
143
+ // end.append(CRLF).append("-----").append(CRLF);
144
+ // serverHttpResponse.writeWith(strToDataBuffer(dataBufferFactory, end.toString()));
145
+ // serverHttpResponse.setComplete();
146
+ //
147
+ // });
148
+
149
+ // serverHttpResponse.beforeCommit(() -> {
150
+ // System.out.println("BEFORE COMMIT");
151
+ // });
152
+
153
+ Flux <Mono <DataBuffer >> dataBufferFlux = Flux .create (monoFluxSink -> {
154
+
155
+ Mono <DataBuffer > firstDataBuffer = firstResult (executionResult );
156
+ monoFluxSink .next (firstDataBuffer );
157
+
158
+ deferredResults .subscribe (new Subscriber <DeferredExecutionResult >() {
131
159
132
- @ Override
133
- public void onNext (DeferredExecutionResult executionResult ) {
134
- try {
135
- DeferPart deferPart = new DeferPart (executionResult .toSpecification ());
136
- String body = deferPart .write ();
137
- writer .append (CRLF ).append ("---" ).append (CRLF );
138
- writer .write (body );
139
- httpServletResponse .flushBuffer ();
160
+ Subscription subscription ;
161
+
162
+ @ Override
163
+ public void onSubscribe (Subscription s ) {
164
+ subscription = s ;
140
165
subscription .request (10 );
141
- } catch (Exception e ) {
142
- e .printStackTrace ();
143
166
}
144
- }
145
167
146
- @ Override
147
- public void onError (Throwable t ) {
148
- t .printStackTrace ();
149
- }
168
+ @ Override
169
+ public void onNext (DeferredExecutionResult executionResult ) {
170
+ try {
171
+ // DeferPart deferPart = new DeferPart(executionResult.toSpecification());
172
+ // String body = deferPart.write();
173
+ // writer.append(CRLF).append("---").append(CRLF);
174
+ // writer.write(body);
175
+ System .out .println ("is comitted:" + serverHttpResponse .isCommitted ());
176
+ DeferPart deferPart = new DeferPart (executionResult .toSpecification ());
177
+ StringBuilder builder = new StringBuilder ();
178
+ String body = deferPart .write ();
179
+ System .out .println ("body:" + body );
180
+ builder .append (CRLF ).append ("---" ).append (CRLF );
181
+ builder .append (body );
182
+ Mono <DataBuffer > dataBuffer = strToDataBuffer (builder .toString ());
183
+ monoFluxSink .next (dataBuffer );
184
+ } catch (Exception e ) {
185
+ e .printStackTrace ();
186
+ }
187
+ }
188
+
189
+ @ Override
190
+ public void onError (Throwable t ) {
191
+ t .printStackTrace ();
192
+ }
193
+
194
+ @ Override
195
+ public void onComplete () {
196
+ // writer.append(CRLF).append("-----").append(CRLF);
197
+ // writer.close();
198
+ // asyncContext.complete();
199
+ System .out .println ("END!!!" );
200
+ StringBuilder end = new StringBuilder ();
201
+ end .append (CRLF ).append ("-----" ).append (CRLF );
202
+ Mono <DataBuffer > dataBuffer = strToDataBuffer (end .toString ());
203
+ monoFluxSink .next (dataBuffer );
204
+ // serverHttpResponse.writeAndFlushWith(Mono.just().subscribe(aVoid -> {
205
+ // System.out.println("done END");
206
+ // }, throwable -> {
207
+ // throwable.printStackTrace();
208
+ // }, () -> {
209
+ // System.out.println("completed END");
210
+ // serverHttpResponse.setComplete();
211
+ // });
212
+ }
213
+ });
150
214
151
- @ Override
152
- public void onComplete () {
153
- writer .append (CRLF ).append ("-----" ).append (CRLF );
154
- writer .close ();
155
- asyncContext .complete ();
156
- }
157
215
});
158
216
217
+ return serverHttpResponse .writeAndFlushWith (dataBufferFlux );
218
+ }
219
+
220
+ private Mono <DataBuffer > firstResult (ExecutionResult executionResult ) {
221
+ StringBuilder builder = new StringBuilder ();
222
+ builder .append (CRLF ).append ("---" ).append (CRLF );
223
+ DeferPart deferPart = new DeferPart (executionResult .toSpecification ());
224
+ String body = deferPart .write ();
225
+ builder .append (body );
226
+ Mono <DataBuffer > dataBufferMono = strToDataBuffer (body );
227
+ return dataBufferMono ;
228
+ }
159
229
230
+ private Mono <DataBuffer > strToDataBuffer (String string ) {
231
+ byte [] bytes = string .getBytes (StandardCharsets .UTF_8 );
232
+ DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory ();
233
+ return Mono .just (defaultDataBufferFactory .wrap (bytes ));
160
234
}
161
235
162
236
private class DeferPart {
0 commit comments