diff --git a/server/implementation-cdi/src/main/java/io/smallrye/graphql/cdi/context/CDISmallRyeContext.java b/server/implementation-cdi/src/main/java/io/smallrye/graphql/cdi/context/CDISmallRyeContext.java index 984a56f62..1cb692e60 100644 --- a/server/implementation-cdi/src/main/java/io/smallrye/graphql/cdi/context/CDISmallRyeContext.java +++ b/server/implementation-cdi/src/main/java/io/smallrye/graphql/cdi/context/CDISmallRyeContext.java @@ -256,4 +256,19 @@ public boolean hasRequest() { public String toString() { return SmallRyeContextManager.getCurrentSmallRyeContext().toString(); } + + @Override + public Map getAddedExtensions() { + return SmallRyeContextManager.getCurrentSmallRyeContext().getAddedExtensions(); + } + + @Override + public void setAddedExtensions(Map addedExtensions) { + SmallRyeContextManager.getCurrentSmallRyeContext().setAddedExtensions(addedExtensions); + } + + @Override + public void addExtension(String key, Object value) { + SmallRyeContextManager.getCurrentSmallRyeContext().addExtension(key, value); + } } diff --git a/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionResponse.java b/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionResponse.java index 65e495aca..3bbf2e7a9 100644 --- a/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionResponse.java +++ b/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionResponse.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,8 +43,15 @@ public class ExecutionResponse { private final ExecutionResult executionResult; + private Map addedExtensions; + public ExecutionResponse(ExecutionResult executionResult) { + this(executionResult, null); + } + + public ExecutionResponse(ExecutionResult executionResult, Map addedExtensions) { this.executionResult = executionResult; + this.addedExtensions = addedExtensions; } public String toString() { @@ -97,13 +105,19 @@ private JsonObjectBuilder addDataToResponse(JsonObjectBuilder returnObjectBuilde private JsonObjectBuilder addExtensionsToResponse(JsonObjectBuilder returnObjectBuilder, ExecutionResult executionResult) { final Map extensions = executionResult.getExtensions(); - if (extensions != null) { - JsonObject extensionsObject = buildExtensions(extensions); - returnObjectBuilder = returnObjectBuilder.add(EXTENSIONS, extensionsObject); + if (extensions != null) { // ERRORS + returnObjectBuilder = addExtensionToBuilder(extensions, returnObjectBuilder); + } else if (addedExtensions != null && !addedExtensions.isEmpty()) { // ADDED EXTENSIONS + returnObjectBuilder = addExtensionToBuilder(new HashMap(addedExtensions), returnObjectBuilder); } return returnObjectBuilder; } + private JsonObjectBuilder addExtensionToBuilder(Map extensions, JsonObjectBuilder returnObjectBuilder) { + JsonObject extensionsObject = buildExtensions(extensions); + return returnObjectBuilder.add(EXTENSIONS, extensionsObject); + } + private JsonObject buildExtensions(final Map extensions) { JsonObjectBuilder extensionsBuilder = jsonObjectFactory.createObjectBuilder(); for (final Map.Entry entry : extensions.entrySet()) { diff --git a/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionService.java b/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionService.java index e3f660a63..266124852 100644 --- a/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionService.java +++ b/server/implementation/src/main/java/io/smallrye/graphql/execution/ExecutionService.java @@ -237,11 +237,11 @@ private void notifyAndWrite(SmallRyeContext smallRyeContext, ExecutionResult executionResult, ExecutionResponseWriter writer) { smallRyeContext.setExecutionResult(executionResult); - // Notify after eventEmitter.fireAfterExecute(smallRyeContext); - ExecutionResponse executionResponse = new ExecutionResponse(executionResult); + ExecutionResponse executionResponse = new ExecutionResponse(executionResult, + smallRyeContext.getAddedExtensions()); if (!payloadOption.equals(LogPayloadOption.off)) { log.payloadOut(executionResponse.toString()); } diff --git a/server/implementation/src/main/java/io/smallrye/graphql/execution/context/SmallRyeContext.java b/server/implementation/src/main/java/io/smallrye/graphql/execution/context/SmallRyeContext.java index d6bed4847..04d0ed8c5 100644 --- a/server/implementation/src/main/java/io/smallrye/graphql/execution/context/SmallRyeContext.java +++ b/server/implementation/src/main/java/io/smallrye/graphql/execution/context/SmallRyeContext.java @@ -2,6 +2,7 @@ import static io.smallrye.graphql.SmallRyeGraphQLServerMessages.msg; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -42,6 +43,19 @@ public class SmallRyeContext implements Context { private QueryCache queryCache; private DocumentSupplier documentSupplier; private ExecutionResult executionResult; + private Map addedExtensions = new HashMap<>(); + + public Map getAddedExtensions() { + return addedExtensions; + } + + public void setAddedExtensions(Map addedExtensions) { + this.addedExtensions = addedExtensions; + } + + public void addExtension(String key, Object value) { + addedExtensions.put(key, value); + } public SmallRyeContext(String createdBy) { this.createdBy = createdBy; diff --git a/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/Shirt.java b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/Shirt.java new file mode 100644 index 000000000..ee0021800 --- /dev/null +++ b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/Shirt.java @@ -0,0 +1,16 @@ +package io.smallrye.graphql.tests.extensions; + +public class Shirt { + private long size; + + public Shirt() { + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } +} diff --git a/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/ShirtResource.java b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/ShirtResource.java new file mode 100644 index 000000000..0eb1ffc1f --- /dev/null +++ b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/ShirtResource.java @@ -0,0 +1,24 @@ +package io.smallrye.graphql.tests.extensions; + +import java.util.List; + +import jakarta.inject.Inject; + +import org.eclipse.microprofile.graphql.GraphQLApi; +import org.eclipse.microprofile.graphql.Query; + +import io.smallrye.graphql.execution.context.SmallRyeContext; + +@GraphQLApi +public class ShirtResource { + + @Inject + SmallRyeContext smallRyeContext; + + @Query + public List getShirts() { + smallRyeContext.addExtension("bar", "This is test for extensions"); + smallRyeContext.addExtension("foo", 3.14159); + return null; + } +} diff --git a/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/UserSupportedExtensionsTest.java b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/UserSupportedExtensionsTest.java new file mode 100644 index 000000000..7defcc5ce --- /dev/null +++ b/server/integration-tests/src/test/java/io/smallrye/graphql/tests/extensions/UserSupportedExtensionsTest.java @@ -0,0 +1,42 @@ +package io.smallrye.graphql.tests.extensions; + +import java.net.URL; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import io.smallrye.graphql.tests.GraphQLAssured; + +@RunWith(Arquillian.class) +@RunAsClient +public class UserSupportedExtensionsTest { + + @Deployment + public static WebArchive deployment() { + return ShrinkWrap.create(WebArchive.class, "user-extensions.war") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .addClasses(Shirt.class, ShirtResource.class); + } + + @ArquillianResource + URL testingURL; + + @Test + public void userAddedExtension() { + GraphQLAssured graphQLAssured = new GraphQLAssured(testingURL); + String request = "query { shirts { size } }"; + String response = graphQLAssured.post(request); + MatcherAssert.assertThat(response, Matchers.containsString("\"extensions\":")); + MatcherAssert.assertThat(response, Matchers.containsString("\"bar\":\"This is test for extensions\"")); + MatcherAssert.assertThat(response, Matchers.containsString("\"foo\":3.14159")); + } +}