Skip to content

Commit f8fbadb

Browse files
authored
Merge pull request #338 from graphql-java-kickstart/bugfix/293-async-call-listeners
fix(#293): move listener callbacks into new invoker
2 parents c9e5827 + 4b43e0c commit f8fbadb

18 files changed

+2448
-2253
lines changed

.idea/codeStyles/Project.xml

+11-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

graphql-java-servlet/src/main/java/graphql/kickstart/servlet/AbstractGraphQLHttpServlet.java

-38
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
import graphql.kickstart.servlet.core.GraphQLMBean;
99
import graphql.kickstart.servlet.core.GraphQLServletListener;
1010
import graphql.schema.GraphQLFieldDefinition;
11-
import java.util.List;
12-
import java.util.Objects;
13-
import java.util.function.Consumer;
14-
import java.util.function.Function;
15-
import java.util.stream.Collectors;
1611
import javax.servlet.Servlet;
1712
import javax.servlet.http.HttpServlet;
1813
import javax.servlet.http.HttpServletRequest;
@@ -85,43 +80,10 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
8580
}
8681

8782
private void doRequest(HttpServletRequest request, HttpServletResponse response) {
88-
List<GraphQLServletListener.RequestCallback> requestCallbacks =
89-
runListeners(l -> l.onRequest(request, response));
90-
9183
try {
9284
getConfiguration().getHttpRequestHandler().handle(request, response);
93-
runCallbacks(requestCallbacks, c -> c.onSuccess(request, response));
9485
} catch (Exception t) {
9586
log.error("Error executing GraphQL request!", t);
96-
runCallbacks(requestCallbacks, c -> c.onError(request, response, t));
97-
} finally {
98-
runCallbacks(requestCallbacks, c -> c.onFinally(request, response));
9987
}
10088
}
101-
102-
private <R> List<R> runListeners(Function<? super GraphQLServletListener, R> action) {
103-
return getConfiguration().getListeners().stream()
104-
.map(
105-
listener -> {
106-
try {
107-
return action.apply(listener);
108-
} catch (Exception t) {
109-
log.error("Error running listener: {}", listener, t);
110-
return null;
111-
}
112-
})
113-
.filter(Objects::nonNull)
114-
.collect(Collectors.toList());
115-
}
116-
117-
private <T> void runCallbacks(List<T> callbacks, Consumer<T> action) {
118-
callbacks.forEach(
119-
callback -> {
120-
try {
121-
action.accept(callback);
122-
} catch (Exception t) {
123-
log.error("Error running callback: {}", callback, t);
124-
}
125-
});
126-
}
12789
}

graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java

+22-11
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,37 @@ public void execute(
3737
? request.getAsyncContext()
3838
: request.startAsync(request, response);
3939
asyncContext.setTimeout(configuration.getAsyncTimeout());
40-
invoke(invocationInput, request, response)
41-
.thenAccept(result -> writeResultResponse(invocationInput, result, request, response))
42-
.exceptionally(t -> writeErrorResponse(t, response))
40+
invokeAndHandle(invocationInput, request, response)
4341
.thenAccept(aVoid -> asyncContext.complete());
4442
} else {
45-
try {
46-
GraphQLQueryResult result = invoke(invocationInput, request, response).join();
47-
writeResultResponse(invocationInput, result, request, response);
48-
} catch (Exception t) {
49-
writeErrorResponse(t, response);
50-
}
43+
invokeAndHandle(invocationInput, request, response).join();
5144
}
5245
}
5346

47+
private CompletableFuture<Void> invokeAndHandle(
48+
GraphQLInvocationInput invocationInput,
49+
HttpServletRequest request,
50+
HttpServletResponse response) {
51+
ListenerHandler listenerHandler =
52+
ListenerHandler.start(request, response, configuration.getListeners());
53+
return invoke(invocationInput, request, response)
54+
.thenAccept(
55+
result ->
56+
writeResultResponse(invocationInput, result, request, response, listenerHandler))
57+
.exceptionally(t -> writeErrorResponse(t, response, listenerHandler))
58+
.thenAccept(aVoid -> listenerHandler.onFinally());
59+
}
60+
5461
private void writeResultResponse(
5562
GraphQLInvocationInput invocationInput,
5663
GraphQLQueryResult queryResult,
5764
HttpServletRequest request,
58-
HttpServletResponse response) {
65+
HttpServletResponse response,
66+
ListenerHandler listenerHandler) {
5967
QueryResponseWriter queryResponseWriter = createWriter(invocationInput, queryResult);
6068
try {
6169
queryResponseWriter.write(request, response);
70+
listenerHandler.onSuccess();
6271
} catch (IOException e) {
6372
throw new UncheckedIOException(e);
6473
}
@@ -69,10 +78,12 @@ protected QueryResponseWriter createWriter(
6978
return queryResponseWriterFactory.createWriter(invocationInput, queryResult, configuration);
7079
}
7180

72-
private Void writeErrorResponse(Throwable t, HttpServletResponse response) {
81+
private Void writeErrorResponse(
82+
Throwable t, HttpServletResponse response, ListenerHandler listenerHandler) {
7383
response.setStatus(STATUS_BAD_REQUEST);
7484
log.info(
7585
"Bad request: path was not \"/schema.json\" or no query variable named \"query\" given", t);
86+
listenerHandler.onError(t);
7687
return null;
7788
}
7889

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package graphql.kickstart.servlet;
2+
3+
import static java.util.Collections.emptyList;
4+
5+
import graphql.kickstart.servlet.core.GraphQLServletListener;
6+
import graphql.kickstart.servlet.core.GraphQLServletListener.RequestCallback;
7+
import java.util.List;
8+
import java.util.Objects;
9+
import java.util.function.Consumer;
10+
import java.util.function.Function;
11+
import java.util.stream.Collectors;
12+
import javax.servlet.http.HttpServletRequest;
13+
import javax.servlet.http.HttpServletResponse;
14+
import lombok.RequiredArgsConstructor;
15+
import lombok.extern.slf4j.Slf4j;
16+
17+
@Slf4j
18+
@RequiredArgsConstructor
19+
class ListenerHandler {
20+
21+
private final List<RequestCallback> callbacks;
22+
private final HttpServletRequest request;
23+
private final HttpServletResponse response;
24+
25+
static ListenerHandler start(
26+
HttpServletRequest request,
27+
HttpServletResponse response,
28+
List<GraphQLServletListener> listeners) {
29+
if (listeners != null) {
30+
return new ListenerHandler(
31+
runListeners(listeners, it -> it.onRequest(request, response)), request, response);
32+
}
33+
return new ListenerHandler(emptyList(), request, response);
34+
}
35+
36+
private static <R> List<R> runListeners(
37+
List<GraphQLServletListener> listeners, Function<? super GraphQLServletListener, R> action) {
38+
return listeners.stream()
39+
.map(
40+
listener -> {
41+
try {
42+
return action.apply(listener);
43+
} catch (Exception t) {
44+
log.error("Error running listener: {}", listener, t);
45+
return null;
46+
}
47+
})
48+
.filter(Objects::nonNull)
49+
.collect(Collectors.toList());
50+
}
51+
52+
void runCallbacks(Consumer<RequestCallback> action) {
53+
callbacks.forEach(
54+
callback -> {
55+
try {
56+
action.accept(callback);
57+
} catch (Exception t) {
58+
log.error("Error running callback: {}", callback, t);
59+
}
60+
});
61+
}
62+
63+
void onSuccess() {
64+
runCallbacks(it -> it.onSuccess(request, response));
65+
}
66+
67+
void onError(Throwable throwable) {
68+
runCallbacks(it -> it.onError(request, response, throwable));
69+
}
70+
71+
void onFinally() {
72+
runCallbacks(it -> it.onFinally(request, response));
73+
}
74+
}

0 commit comments

Comments
 (0)