From a01b1009a133611f3f4285ac04c6dd940098649e Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Tue, 5 Mar 2024 13:25:06 -0500 Subject: [PATCH 1/2] Ensure reactive context is propagated DefaultGraphQLInvocation and DefaultGraphQLExecutionInputCustomizer are updated to use Mono and Flux in their internal implementation in order to ensure that the Micronaut PropagationContext is carried appropriately through the invocation flow. Previous use of the bare io.micronaut.core.async.publisher.Publishers API in DefaultGraphQLExecutionInputCustomizer was causing the context not to be propagated as desired when including the Micrometer Context Propagation library. A test is added to verify the context propagation works as expected. Some additional cleanup is done throughout the test suite to reduce the scope of included Micronaut beans to the specific tests in order to make it easier to test different setups. Resolves #495 --- gradle/libs.versions.toml | 3 +- graphql/build.gradle | 2 + ...efaultGraphQLExecutionInputCustomizer.java | 4 +- .../graphql/DefaultGraphQLInvocation.java | 6 +- .../graphql/GraphQLConfigurationSpec.groovy | 32 +++++- .../GraphQLContextPropagationSpec.groovy | 104 ++++++++++++++++++ .../graphql/GraphQLControllerSpec.groovy | 2 +- .../graphql/GraphQLFactory.groovy | 23 ---- .../graphql/GraphiQLConfigurationSpec.groovy | 33 +++++- .../graphql/GraphiQLControllerSpec.groovy | 19 ++++ .../ws/GraphQLWsConfigurationSpec.groovy | 36 +++++- .../GraphQLApolloWsConfigurationSpec.groovy | 39 ++++++- graphql/src/test/resources/schema.graphqls | 4 + settings.gradle | 1 + 14 files changed, 259 insertions(+), 49 deletions(-) create mode 100644 graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLContextPropagationSpec.groovy delete mode 100644 graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLFactory.groovy create mode 100644 graphql/src/test/resources/schema.graphqls diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67f2ee1e..198341b0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,6 @@ micronaut-platform = "4.1.2" micronaut-test = "4.0.0" groovy = "4.0.13" spock = "2.3-groovy-4.0" - graal-svm = "23.1.2" kotlin = '1.9.22' shadow = '8.0.0' @@ -14,6 +13,7 @@ micronaut-kotlin = "4.2.0" micronaut-security = "4.6.6" micronaut-serde = "2.8.1" micronaut-logging = "1.1.2" +micronaut-reactor = "3.2.1" managed-graphql-java = "21.3" managed-graphql-java-extended-scalars = "2023-01-24T02-11-56-babda5f" @@ -26,6 +26,7 @@ micronaut-core = { module = 'io.micronaut:micronaut-core-bom', version.ref = 'mi micronaut-kotlin = { module = "io.micronaut.kotlin:micronaut-kotlin-bom", version.ref = "micronaut-kotlin" } micronaut-security = { module = "io.micronaut.security:micronaut-security-bom", version.ref = "micronaut-security" } micronaut-serde = { module = "io.micronaut.serde:micronaut-serde-bom", version.ref = "micronaut-serde" } +micronaut-reactor = { module = "io.micronaut.reactor:micronaut-reactor-bom", version.ref = "micronaut-reactor" } managed-graphql-java = { module = 'com.graphql-java:graphql-java', version.ref = 'managed-graphql-java' } managed-graphql-java-extended-scalars = { module = 'com.graphql-java:graphql-java-extended-scalars', version.ref = 'managed-graphql-java-extended-scalars' } diff --git a/graphql/build.gradle b/graphql/build.gradle index 93d8868a..b3c6cf80 100644 --- a/graphql/build.gradle +++ b/graphql/build.gradle @@ -17,6 +17,8 @@ dependencies { testImplementation(mn.micronaut.http.server.netty) testImplementation(mn.micronaut.http.client) testRuntimeOnly(mn.snakeyaml) + testRuntimeOnly(mnReactor.micronaut.reactor) + testRuntimeOnly(mnReactor.micrometer.context.propagation) } micronautBuild { diff --git a/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLExecutionInputCustomizer.java b/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLExecutionInputCustomizer.java index 719a91d6..701c66e8 100644 --- a/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLExecutionInputCustomizer.java +++ b/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLExecutionInputCustomizer.java @@ -18,11 +18,11 @@ import graphql.ExecutionInput; import io.micronaut.context.annotation.Requires; import io.micronaut.core.annotation.Nullable; -import io.micronaut.core.async.publisher.Publishers; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import jakarta.inject.Singleton; import org.reactivestreams.Publisher; +import reactor.core.publisher.Mono; /** * The default implementation for customizing GraphQL execution inputs. @@ -42,6 +42,6 @@ public Publisher customize( ExecutionInput executionInput, HttpRequest httpRequest, @Nullable MutableHttpResponse httpResponse) { - return Publishers.just(executionInput); + return Mono.just(executionInput); } } diff --git a/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLInvocation.java b/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLInvocation.java index b9cd3a8d..12f87b2e 100644 --- a/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLInvocation.java +++ b/graphql/src/main/java/io/micronaut/configuration/graphql/DefaultGraphQLInvocation.java @@ -20,13 +20,13 @@ import graphql.GraphQL; import io.micronaut.context.BeanProvider; import io.micronaut.core.annotation.Nullable; -import io.micronaut.core.async.publisher.Publishers; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import jakarta.inject.Singleton; import org.dataloader.DataLoaderRegistry; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import java.util.concurrent.CompletableFuture; @@ -81,11 +81,11 @@ public Publisher invoke( ExecutionInput executionInput = executionInputBuilder.build(); return Flux .from(graphQLExecutionInputCustomizer.customize(executionInput, httpRequest, httpResponse)) - .flatMap(customizedExecutionInput -> Publishers.fromCompletableFuture(() -> { + .flatMap(customizedExecutionInput -> Mono.fromFuture(() -> { try { return graphQL.executeAsync(customizedExecutionInput); } catch (Throwable e) { - CompletableFuture future = new CompletableFuture(); + CompletableFuture future = new CompletableFuture<>(); future.completeExceptionally(e); return future; } diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy index 3bce31ca..d682f730 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy @@ -17,11 +17,17 @@ package io.micronaut.configuration.graphql import graphql.GraphQL +import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource +import io.micronaut.core.util.StringUtils import io.micronaut.http.annotation.Controller +import jakarta.inject.Singleton import spock.lang.Specification /** @@ -35,7 +41,8 @@ class GraphQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.factory": false] + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.factory": false] )) context.start() @@ -51,7 +58,9 @@ class GraphQLConfigurationSpec extends Specification { void "test graphql bean provided"() { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.registerSingleton(Mock(GraphQL)) + context.environment.addPropertySource(PropertySource.of( + ["spec.name": GraphQLConfigurationSpec.simpleName] + )) context.start() expect: @@ -68,7 +77,8 @@ class GraphQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.path": "/custom-graphql"] + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.path": "/custom-graphql"] )) context.start() @@ -87,7 +97,8 @@ class GraphQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.enabled": false] + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.enabled": false] )) context.start() @@ -99,4 +110,17 @@ class GraphQLConfigurationSpec extends Specification { cleanup: context.close() } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "graphql.factory", notEquals = StringUtils.FALSE) + @Requires(property = "spec.name", value = "GraphQLConfigurationSpec") + GraphQL graphQL() { + def schema = GraphQLSchema.newSchema().build() + GraphQL.newGraphQL(schema).build() + } + } } diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLContextPropagationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLContextPropagationSpec.groovy new file mode 100644 index 00000000..5791f1f5 --- /dev/null +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLContextPropagationSpec.groovy @@ -0,0 +1,104 @@ +package io.micronaut.configuration.graphql + +import graphql.GraphQL +import graphql.schema.DataFetcher +import graphql.schema.DataFetchingEnvironment +import graphql.schema.GraphQLSchema +import graphql.schema.idl.RuntimeWiring +import graphql.schema.idl.SchemaGenerator +import graphql.schema.idl.SchemaParser +import graphql.schema.idl.TypeDefinitionRegistry +import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires +import io.micronaut.context.env.Environment +import io.micronaut.core.annotation.Nullable +import io.micronaut.core.io.ResourceResolver +import io.micronaut.http.HttpResponse +import io.micronaut.http.annotation.Body +import io.micronaut.http.annotation.Get +import io.micronaut.http.annotation.Post +import io.micronaut.http.annotation.QueryValue +import io.micronaut.http.client.annotation.Client +import io.micronaut.http.context.ServerRequestContext +import io.micronaut.runtime.server.EmbeddedServer +import jakarta.inject.Singleton +import spock.lang.AutoCleanup +import spock.lang.Specification + +import java.net.http.HttpRequest + +class GraphQLContextPropagationSpec extends Specification { + + @AutoCleanup + EmbeddedServer embeddedServer + + GraphQLClient graphQLClient + + def setup() { + embeddedServer = ApplicationContext.run( + EmbeddedServer, + ["spec.name": GraphQLContextPropagationSpec.simpleName]) + graphQLClient = embeddedServer.applicationContext.getBean(GraphQLClient) + } + + void "server request context is propagated to data fetcher"() { + when: + GraphQLResponseBody response = graphQLClient.hello("query { hello }") + + then: + response + response.getSpecification()["data"]["hello"] == "Hello World!" + } + + @Client("/graphql") + static interface GraphQLClient { + + @Get("{?query}") + GraphQLResponseBody hello(@QueryValue String query) + + } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "spec.name", value = "GraphQLContextPropagationSpec") + GraphQL graphQL(ResourceResolver resourceResolver, HelloDataFetcher helloDataFetcher) { + + SchemaParser schemaParser = new SchemaParser() + SchemaGenerator schemaGenerator = new SchemaGenerator() + + TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry() + typeRegistry.merge(schemaParser.parse(new BufferedReader(new InputStreamReader( + resourceResolver.getResourceAsStream("classpath:schema.graphqls").get())))) + + RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() + .type("Query", typeWiring -> typeWiring + .dataFetcher("hello", helloDataFetcher)) + .build() + + GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring) + + return GraphQL.newGraphQL(graphQLSchema).build() + } + } + + @Singleton + @Requires(property = "spec.name", value = "GraphQLContextPropagationSpec") + static class HelloDataFetcher implements DataFetcher { + + @Override + String get(DataFetchingEnvironment env) { + Optional request = ServerRequestContext.currentRequest() + assert request.isPresent() + String name = env.getArgument("name") + if (name == null || name.trim().length() == 0) { + name = "World" + } + return String.format("Hello %s!", name) + } + } +} diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLControllerSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLControllerSpec.groovy index 26bc6b82..e9587f56 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLControllerSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLControllerSpec.groovy @@ -301,7 +301,7 @@ class GraphQLControllerSpec extends Specification { } @Factory - class GraphQLFactory { + static class GraphQLFactory { @Bean @Singleton diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLFactory.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLFactory.groovy deleted file mode 100644 index 070db825..00000000 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLFactory.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package io.micronaut.configuration.graphql - -import graphql.GraphQL -import graphql.schema.GraphQLSchema -import io.micronaut.context.annotation.Factory -import io.micronaut.context.annotation.Requires -import io.micronaut.core.util.StringUtils -import jakarta.inject.Singleton - -/** - * @author James Kleeh - * @since 1.0 - */ -@Factory -class GraphQLFactory { - - @Requires(property = "graphql.factory", notEquals = StringUtils.FALSE) - @Singleton - GraphQL graphQL() { - def schema = GraphQLSchema.newSchema().build() - GraphQL.newGraphQL(schema).build() - } -} diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy index 1ad28646..e59d3398 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy @@ -16,11 +16,17 @@ package io.micronaut.configuration.graphql +import graphql.GraphQL +import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource import io.micronaut.http.annotation.Controller +import jakarta.inject.Singleton import spock.lang.Specification /** @@ -32,6 +38,9 @@ class GraphiQLConfigurationSpec extends Specification { void "test graphiql disabled by default"() { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) + context.environment.addPropertySource(PropertySource.of( + ["spec.name": GraphQLConfigurationSpec.simpleName] + )) context.start() expect: @@ -45,7 +54,8 @@ class GraphiQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphiql.enabled": true] + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true] )) context.start() @@ -61,7 +71,8 @@ class GraphiQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphiql.enabled": true, + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true, "graphql.graphiql.version" : "0.13.1"] )) context.start() @@ -78,7 +89,8 @@ class GraphiQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphiql.enabled": true, + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true, "graphql.graphiql.path" : "/custom-graphiql"] )) context.start() @@ -96,7 +108,8 @@ class GraphiQLConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphiql.enabled": false] + ["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": false] )) context.start() @@ -106,4 +119,16 @@ class GraphiQLConfigurationSpec extends Specification { cleanup: context.close() } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "spec.name", value = "GraphiQLConfigurationSpec") + GraphQL graphQL() { + def schema = GraphQLSchema.newSchema().build() + GraphQL.newGraphQL(schema).build() + } + } } diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLControllerSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLControllerSpec.groovy index e856e984..50fffb15 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLControllerSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLControllerSpec.groovy @@ -16,13 +16,20 @@ package io.micronaut.configuration.graphql +import graphql.GraphQL +import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment +import io.micronaut.core.util.StringUtils import io.micronaut.http.HttpRequest import io.micronaut.http.HttpResponse import io.micronaut.http.HttpStatus import io.micronaut.http.client.HttpClient import io.micronaut.runtime.server.EmbeddedServer +import jakarta.inject.Singleton import spock.lang.Specification import static io.micronaut.http.MediaType.TEXT_HTML @@ -75,4 +82,16 @@ class GraphiQLControllerSpec extends Specification { cleanup: embeddedServer.close() } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "spec.name", value = "GraphiQLControllerSpec") + GraphQL graphQL() { + def schema = GraphQLSchema.newSchema().build() + GraphQL.newGraphQL(schema).build() + } + } } diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy index 95185a8e..e1aad4c5 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy @@ -1,11 +1,17 @@ package io.micronaut.configuration.graphql.ws - +import graphql.GraphQL +import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource +import io.micronaut.core.util.StringUtils import io.micronaut.websocket.annotation.ServerWebSocket +import jakarta.inject.Singleton import spock.lang.Specification import java.time.Duration @@ -15,6 +21,9 @@ class GraphQLWsConfigurationSpec extends Specification { void "test graphql websocket disabled by default"() { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) + context.environment.addPropertySource(PropertySource.of( + ["spec.name": GraphQLWsConfigurationSpec.simpleName] + )) context.start() expect: @@ -28,7 +37,8 @@ class GraphQLWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-ws.enabled": true] + ["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": true] )) context.start() @@ -50,7 +60,8 @@ class GraphQLWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-ws.enabled" : true, + ["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled" : true, "graphql.graphql-ws.connection-init-wait-timeout": "30s"] )) context.start() @@ -73,7 +84,8 @@ class GraphQLWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-ws.enabled": true, + ["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": true, "graphql.graphql-ws.path" : "/custom-graphql-ws"] )) context.start() @@ -91,7 +103,8 @@ class GraphQLWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-ws.enabled": false] + ["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": false] )) context.start() @@ -101,4 +114,17 @@ class GraphQLWsConfigurationSpec extends Specification { cleanup: context.close() } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "graphql.factory", notEquals = StringUtils.FALSE) + @Requires(property = "spec.name", value = "GraphQLWsConfigurationSpec") + GraphQL graphQL() { + def schema = GraphQLSchema.newSchema().build() + GraphQL.newGraphQL(schema).build() + } + } } diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy index 35fcb0fc..590c7f67 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy @@ -1,10 +1,16 @@ package io.micronaut.configuration.graphql.ws.apollo +import graphql.GraphQL +import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext import io.micronaut.context.DefaultApplicationContext +import io.micronaut.context.annotation.Bean +import io.micronaut.context.annotation.Factory +import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment import io.micronaut.context.env.PropertySource import io.micronaut.websocket.annotation.ServerWebSocket +import jakarta.inject.Singleton import spock.lang.Specification /** @@ -16,6 +22,9 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket disabled by default"() { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) + context.environment.addPropertySource(PropertySource.of( + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName] + )) context.start() expect: @@ -29,7 +38,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.enabled": true] + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": true] )) context.start() @@ -52,7 +62,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.enabled": true, + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": true, "graphql.graphql-apollo-ws.path" : "/custom-graphql-ws"] )) context.start() @@ -70,7 +81,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.enabled": false] + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": false] )) context.start() @@ -85,7 +97,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.keep-alive-enabled": false] + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-enabled": false] )) context.start() @@ -100,7 +113,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.keep-alive-enabled": false] + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-enabled": false] )) context.start() @@ -115,7 +129,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { given: ApplicationContext context = new DefaultApplicationContext(Environment.TEST) context.environment.addPropertySource(PropertySource.of( - ["graphql.graphql-apollo-ws.keep-alive-interval": "1s"] + ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-interval": "1s"] )) context.start() @@ -125,4 +140,16 @@ class GraphQLApolloWsConfigurationSpec extends Specification { cleanup: context.close() } + + @Factory + static class GraphQLFactory { + + @Bean + @Singleton + @Requires(property = "spec.name", value = "GraphQLApolloWsConfigurationSpec") + GraphQL graphQL() { + def schema = GraphQLSchema.newSchema().build() + GraphQL.newGraphQL(schema).build() + } + } } diff --git a/graphql/src/test/resources/schema.graphqls b/graphql/src/test/resources/schema.graphqls new file mode 100644 index 00000000..6fadd606 --- /dev/null +++ b/graphql/src/test/resources/schema.graphqls @@ -0,0 +1,4 @@ +type Query { + + hello(name: String): String! +} diff --git a/settings.gradle b/settings.gradle index bf2e1efe..4fc9ad1f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,6 +17,7 @@ micronautBuild { importMicronautCatalog("micronaut-kotlin") importMicronautCatalog("micronaut-security") importMicronautCatalog("micronaut-serde") + importMicronautCatalog("micronaut-reactor") } rootProject.name = 'graphql-parent' From 5ebb76d26677c37ee423c2b73b199a71e75846a8 Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Wed, 6 Mar 2024 11:12:00 -0500 Subject: [PATCH 2/2] Avoid direct instantiation of DefaultApplicationContext --- .../graphql/GraphQLConfigurationSpec.groovy | 32 +++------- .../graphql/GraphiQLConfigurationSpec.groovy | 44 ++++---------- .../ws/GraphQLWsConfigurationSpec.groovy | 44 ++++---------- .../GraphQLApolloWsConfigurationSpec.groovy | 59 +++++-------------- 4 files changed, 43 insertions(+), 136 deletions(-) diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy index d682f730..45ffe174 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphQLConfigurationSpec.groovy @@ -19,12 +19,10 @@ package io.micronaut.configuration.graphql import graphql.GraphQL import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext -import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.annotation.Bean import io.micronaut.context.annotation.Factory import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment -import io.micronaut.context.env.PropertySource import io.micronaut.core.util.StringUtils import io.micronaut.http.annotation.Controller import jakarta.inject.Singleton @@ -39,12 +37,8 @@ class GraphQLConfigurationSpec extends Specification { void "test no graphql bean provided"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.factory": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.factory": false], Environment.TEST) expect: !context.containsBean(GraphQLExecutionResultHandler) @@ -57,11 +51,7 @@ class GraphQLConfigurationSpec extends Specification { void "test graphql bean provided"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName], Environment.TEST) expect: context.containsBean(GraphQLExecutionResultHandler) @@ -75,12 +65,8 @@ class GraphQLConfigurationSpec extends Specification { void "test custom graphql path"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.path": "/custom-graphql"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.path": "/custom-graphql"], Environment.TEST) expect: context.containsBean(GraphQLExecutionResultHandler) @@ -95,12 +81,8 @@ class GraphQLConfigurationSpec extends Specification { void "test graphql disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.enabled": false], Environment.TEST) expect: !context.containsBean(GraphQLExecutionResultHandler) diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy index e59d3398..4b851d6b 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/GraphiQLConfigurationSpec.groovy @@ -19,12 +19,10 @@ package io.micronaut.configuration.graphql import graphql.GraphQL import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext -import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.annotation.Bean import io.micronaut.context.annotation.Factory import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment -import io.micronaut.context.env.PropertySource import io.micronaut.http.annotation.Controller import jakarta.inject.Singleton import spock.lang.Specification @@ -37,11 +35,7 @@ class GraphiQLConfigurationSpec extends Specification { void "test graphiql disabled by default"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName], Environment.TEST) expect: !context.containsBean(GraphiQLController) @@ -52,12 +46,8 @@ class GraphiQLConfigurationSpec extends Specification { void "test graphiql enabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.graphiql.enabled": true] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true], Environment.TEST) expect: context.containsBean(GraphiQLController) @@ -69,13 +59,9 @@ class GraphiQLConfigurationSpec extends Specification { void "test custom graphiql version"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.graphiql.enabled": true, - "graphql.graphiql.version" : "0.13.1"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true, + "graphql.graphiql.version" : "0.13.1"], Environment.TEST) expect: context.containsBean(GraphiQLController) @@ -87,13 +73,9 @@ class GraphiQLConfigurationSpec extends Specification { void "test custom graphiql path"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.graphiql.enabled": true, - "graphql.graphiql.path" : "/custom-graphiql"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": true, + "graphql.graphiql.path" : "/custom-graphiql"], Environment.TEST) expect: context.containsBean(GraphiQLController) @@ -106,12 +88,8 @@ class GraphiQLConfigurationSpec extends Specification { void "test graphiql disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLConfigurationSpec.simpleName, - "graphql.graphiql.enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLConfigurationSpec.simpleName, + "graphql.graphiql.enabled": false], Environment.TEST) expect: !context.containsBean(GraphiQLController) diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy index e1aad4c5..286ecb4d 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/GraphQLWsConfigurationSpec.groovy @@ -3,12 +3,10 @@ package io.micronaut.configuration.graphql.ws import graphql.GraphQL import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext -import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.annotation.Bean import io.micronaut.context.annotation.Factory import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment -import io.micronaut.context.env.PropertySource import io.micronaut.core.util.StringUtils import io.micronaut.websocket.annotation.ServerWebSocket import jakarta.inject.Singleton @@ -20,11 +18,7 @@ class GraphQLWsConfigurationSpec extends Specification { void "test graphql websocket disabled by default"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLWsConfigurationSpec.simpleName] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLWsConfigurationSpec.simpleName], Environment.TEST) expect: !context.containsBean(GraphQLWsHandler) @@ -35,12 +29,8 @@ class GraphQLWsConfigurationSpec extends Specification { void "test graphql websocket enabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLWsConfigurationSpec.simpleName, - "graphql.graphql-ws.enabled": true] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": true], Environment.TEST) expect: context.containsBean(GraphQLWsHandler) @@ -58,13 +48,9 @@ class GraphQLWsConfigurationSpec extends Specification { void "test graphql websocket enabled with custom connection timeout"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLWsConfigurationSpec.simpleName, - "graphql.graphql-ws.enabled" : true, - "graphql.graphql-ws.connection-init-wait-timeout": "30s"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled" : true, + "graphql.graphql-ws.connection-init-wait-timeout": "30s"], Environment.TEST) expect: context.containsBean(GraphQLWsHandler) @@ -82,13 +68,9 @@ class GraphQLWsConfigurationSpec extends Specification { void "test custom path"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLWsConfigurationSpec.simpleName, - "graphql.graphql-ws.enabled": true, - "graphql.graphql-ws.path" : "/custom-graphql-ws"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": true, + "graphql.graphql-ws.path" : "/custom-graphql-ws"], Environment.TEST) expect: context.containsBean(GraphQLWsHandler) @@ -101,12 +83,8 @@ class GraphQLWsConfigurationSpec extends Specification { void "test graphql websocket disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLWsConfigurationSpec.simpleName, - "graphql.graphql-ws.enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLWsConfigurationSpec.simpleName, + "graphql.graphql-ws.enabled": false], Environment.TEST) expect: !context.containsBean(GraphQLWsHandler) diff --git a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy index 590c7f67..b48fdd6c 100644 --- a/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy +++ b/graphql/src/test/groovy/io/micronaut/configuration/graphql/ws/apollo/GraphQLApolloWsConfigurationSpec.groovy @@ -3,16 +3,13 @@ package io.micronaut.configuration.graphql.ws.apollo import graphql.GraphQL import graphql.schema.GraphQLSchema import io.micronaut.context.ApplicationContext -import io.micronaut.context.DefaultApplicationContext import io.micronaut.context.annotation.Bean import io.micronaut.context.annotation.Factory import io.micronaut.context.annotation.Requires import io.micronaut.context.env.Environment -import io.micronaut.context.env.PropertySource import io.micronaut.websocket.annotation.ServerWebSocket import jakarta.inject.Singleton import spock.lang.Specification - /** * @author Gerard Klijs * @since 1.3 @@ -21,11 +18,7 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket disabled by default"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName], Environment.TEST) expect: !context.containsBean(GraphQLApolloWsController) @@ -36,12 +29,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket enabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.enabled": true] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": true], Environment.TEST) expect: context.containsBean(GraphQLApolloWsController) @@ -60,13 +49,9 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test custom path"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.enabled": true, - "graphql.graphql-apollo-ws.path" : "/custom-graphql-ws"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": true, + "graphql.graphql-apollo-ws.path" : "/custom-graphql-ws"], Environment.TEST) expect: context.containsBean(GraphQLApolloWsController) @@ -79,12 +64,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.enabled": false], Environment.TEST) expect: !context.containsBean(GraphQLApolloWsController) @@ -95,12 +76,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket keepalive disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.keep-alive-enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-enabled": false], Environment.TEST) expect: !context.getBean(GraphQLApolloWsConfiguration).enabled @@ -111,12 +88,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test bean not created when graphql websocket keepalive disabled"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.keep-alive-enabled": false] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-enabled": false], Environment.TEST) expect: !context.containsBean(GraphQLApolloWsKeepAlive) @@ -127,12 +100,8 @@ class GraphQLApolloWsConfigurationSpec extends Specification { void "test graphql websocket keepalive different interval"() { given: - ApplicationContext context = new DefaultApplicationContext(Environment.TEST) - context.environment.addPropertySource(PropertySource.of( - ["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, - "graphql.graphql-apollo-ws.keep-alive-interval": "1s"] - )) - context.start() + ApplicationContext context = ApplicationContext.run(["spec.name": GraphQLApolloWsConfigurationSpec.simpleName, + "graphql.graphql-apollo-ws.keep-alive-interval": "1s"], Environment.TEST) expect: context.getBean(GraphQLApolloWsConfiguration).keepAliveInterval == "1s"