diff --git a/gradle.properties b/gradle.properties index ace86a27..404f8f90 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,9 +7,10 @@ PROJECT_LICENSE=MIT PROJECT_LICENSE_URL=https://github.com/graphql-java-kickstart/spring-boot-graphql/blob/master/LICENSE.md PROJECT_DEV_ID=apottere PROJECT_DEV_NAME=Andrew Potter -LIB_GRAPHQL_JAVA_VER=17.2 +LIB_GRAPHQL_JAVA_VER=17.3 LIB_JACKSON_VER=2.12.5 LIB_SLF4J_VER=1.7.32 LIB_LOMBOK_VER=1.18.20 SOURCE_COMPATIBILITY=1.8 TARGET_COMPATIBILITY=1.8 +GRADLE_WRAPPER_VER=7.0 diff --git a/graphql-java-servlet/build.gradle b/graphql-java-servlet/build.gradle index 6f4e7019..f6cca231 100644 --- a/graphql-java-servlet/build.gradle +++ b/graphql-java-servlet/build.gradle @@ -31,12 +31,12 @@ dependencies { testImplementation 'io.github.graphql-java:graphql-java-annotations:8.3' // Unit testing - testImplementation "org.codehaus.groovy:groovy-all:3.0.8" + testImplementation "org.codehaus.groovy:groovy-all:3.0.9" testImplementation "org.spockframework:spock-core:2.0-groovy-3.0" testRuntimeOnly "cglib:cglib-nodep:3.3.0" testRuntimeOnly "org.objenesis:objenesis:3.2" testImplementation "org.slf4j:slf4j-simple:$LIB_SLF4J_VER" - testImplementation 'org.springframework:spring-test:5.3.9' - testRuntimeOnly 'org.springframework:spring-web:5.3.9' + testImplementation 'org.springframework:spring-test:5.3.10' + testRuntimeOnly 'org.springframework:spring-web:5.3.10' testImplementation 'com.google.guava:guava:30.1.1-jre' } diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java index 9d10e398..829bf091 100644 --- a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java @@ -91,7 +91,10 @@ private CompletableFuture handle( return futureResult .thenApplyQueryResult() .thenAccept( - it -> writeResultResponse(futureResult.getInvocationInput(), it, request, response)) + it -> { + listenerHandler.beforeFlush(); + writeResultResponse(futureResult.getInvocationInput(), it, request, response); + }) .thenAccept(it -> listenerHandler.onSuccess()) .exceptionally( t -> diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/ListenerHandler.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/ListenerHandler.java index d9461002..faff966d 100644 --- a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/ListenerHandler.java +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/ListenerHandler.java @@ -60,6 +60,10 @@ void runCallbacks(Consumer action) { }); } + void beforeFlush() { + runCallbacks(it -> it.beforeFlush(request, response)); + } + void onSuccess() { runCallbacks(it -> it.onSuccess(request, response)); } diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/core/GraphQLServletListener.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/core/GraphQLServletListener.java index 685d1faf..fc0feb34 100644 --- a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/core/GraphQLServletListener.java +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/core/GraphQLServletListener.java @@ -6,17 +6,50 @@ /** @author Andrew Potter */ public interface GraphQLServletListener { + /** + * Called this method when the request started processing. + * @param request http request + * @param response http response + * @return request callback or {@literal null} + */ default RequestCallback onRequest(HttpServletRequest request, HttpServletResponse response) { return null; } + /** + * The callback which used to add additional listeners for GraphQL request execution. + */ interface RequestCallback { + /** + * Called right before the response will be written and flushed. Can be used for applying some + * changes to the response object, like adding response headers. + * @param request http request + * @param response http response + */ + default void beforeFlush(HttpServletRequest request, HttpServletResponse response) {} + + /** + * Called when GraphQL invoked successfully and the response was written already. + * @param request http request + * @param response http response + */ default void onSuccess(HttpServletRequest request, HttpServletResponse response) {} + /** + * Called when GraphQL was failed and the response was written already. + * @param request http request + * @param response http response + */ default void onError( HttpServletRequest request, HttpServletResponse response, Throwable throwable) {} + /** + * Called finally once on both success and failed GraphQL invocation. The response is also + * already written. + * @param request http request + * @param response http response + */ default void onFinally(HttpServletRequest request, HttpServletResponse response) {} } }