diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiGraphQLHttpServlet.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiGraphQLHttpServlet.java index 85f2e252..e0d303f6 100644 --- a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiGraphQLHttpServlet.java +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiGraphQLHttpServlet.java @@ -15,6 +15,7 @@ import graphql.kickstart.servlet.core.GraphQLServletListener; import graphql.kickstart.servlet.core.GraphQLServletRootObjectBuilder; import graphql.kickstart.servlet.osgi.GraphQLCodeRegistryProvider; +import graphql.kickstart.servlet.osgi.GraphQLDirectiveProvider; import graphql.kickstart.servlet.osgi.GraphQLMutationProvider; import graphql.kickstart.servlet.osgi.GraphQLProvider; import graphql.kickstart.servlet.osgi.GraphQLQueryProvider; @@ -75,6 +76,9 @@ public void bindProvider(GraphQLProvider provider) { if (provider instanceof GraphQLTypesProvider) { schemaBuilder.add((GraphQLTypesProvider) provider); } + if (provider instanceof GraphQLDirectiveProvider) { + schemaBuilder.add((GraphQLDirectiveProvider) provider); + } if (provider instanceof GraphQLCodeRegistryProvider) { schemaBuilder.setCodeRegistryProvider((GraphQLCodeRegistryProvider) provider); } @@ -94,6 +98,9 @@ public void unbindProvider(GraphQLProvider provider) { if (provider instanceof GraphQLTypesProvider) { schemaBuilder.remove((GraphQLTypesProvider) provider); } + if (provider instanceof GraphQLDirectiveProvider) { + schemaBuilder.remove((GraphQLDirectiveProvider) provider); + } if (provider instanceof GraphQLCodeRegistryProvider) { schemaBuilder.setCodeRegistryProvider(() -> GraphQLCodeRegistry.newCodeRegistry().build()); } @@ -144,6 +151,17 @@ public void unbindTypesProvider(GraphQLTypesProvider typesProvider) { updateSchema(); } + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) + public void bindDirectivesProvider(GraphQLDirectiveProvider directiveProvider) { + schemaBuilder.add(directiveProvider); + updateSchema(); + } + + public void unbindDirectivesProvider(GraphQLDirectiveProvider directiveProvider) { + schemaBuilder.remove(directiveProvider); + updateSchema(); + } + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) public void bindServletListener(GraphQLServletListener listener) { schemaBuilder.add(listener); diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiSchemaBuilder.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiSchemaBuilder.java index 880a77a3..ff93a8aa 100644 --- a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiSchemaBuilder.java +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/OsgiSchemaBuilder.java @@ -25,11 +25,13 @@ import graphql.kickstart.servlet.input.GraphQLInvocationInputFactory; import graphql.kickstart.servlet.osgi.GraphQLCodeRegistryProvider; import graphql.kickstart.servlet.osgi.GraphQLFieldProvider; +import graphql.kickstart.servlet.osgi.GraphQLDirectiveProvider; import graphql.kickstart.servlet.osgi.GraphQLMutationProvider; import graphql.kickstart.servlet.osgi.GraphQLQueryProvider; import graphql.kickstart.servlet.osgi.GraphQLSubscriptionProvider; import graphql.kickstart.servlet.osgi.GraphQLTypesProvider; import graphql.schema.GraphQLCodeRegistry; +import graphql.schema.GraphQLDirective; import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLType; @@ -50,6 +52,7 @@ class OsgiSchemaBuilder { private final List mutationProviders = new ArrayList<>(); private final List subscriptionProviders = new ArrayList<>(); private final List typesProviders = new ArrayList<>(); + private final List directiveProviders = new ArrayList<>(); private final List listeners = new ArrayList<>(); private GraphQLServletContextBuilder contextBuilder = new DefaultGraphQLServletContextBuilder(); @@ -103,6 +106,7 @@ private void doUpdateSchema() { .mutation(buildMutationType()) .subscription(buildSubscriptionType()) .additionalTypes(buildTypes()) + .additionalDirectives(buildDirectives()) .codeRegistry(codeRegistryProvider.getCodeRegistry()) .build()); } @@ -159,6 +163,13 @@ private GraphQLObjectType buildObjectType(String name, List buildDirectives() { + return directiveProviders.stream() + .map(GraphQLDirectiveProvider::getDirectives) + .flatMap(Collection::stream) + .collect(toSet()); + } + void add(GraphQLQueryProvider provider) { queryProviders.add(provider); } @@ -175,6 +186,10 @@ void add(GraphQLTypesProvider provider) { typesProviders.add(provider); } + void add(GraphQLDirectiveProvider provider) { + directiveProviders.add(provider); + } + void remove(GraphQLQueryProvider provider) { queryProviders.remove(provider); } @@ -191,6 +206,10 @@ void remove(GraphQLTypesProvider provider) { typesProviders.remove(provider); } + void remove(GraphQLDirectiveProvider provider) { + directiveProviders.remove(provider); + } + GraphQLSchemaServletProvider getSchemaProvider() { return schemaProvider; } diff --git a/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/osgi/GraphQLDirectiveProvider.java b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/osgi/GraphQLDirectiveProvider.java new file mode 100644 index 00000000..b67eb30c --- /dev/null +++ b/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/osgi/GraphQLDirectiveProvider.java @@ -0,0 +1,12 @@ +package graphql.kickstart.servlet.osgi; + +import graphql.schema.GraphQLDirective; +import java.util.Collection; + + +public interface GraphQLDirectiveProvider extends GraphQLProvider { + + /** @return A collection of directive definitions that will be added to the schema. */ + Collection getDirectives(); + +} diff --git a/graphql-java-servlet/src/test/groovy/graphql/kickstart/servlet/OsgiGraphQLHttpServletSpec.groovy b/graphql-java-servlet/src/test/groovy/graphql/kickstart/servlet/OsgiGraphQLHttpServletSpec.groovy index ea4ed23d..0cab0577 100644 --- a/graphql-java-servlet/src/test/groovy/graphql/kickstart/servlet/OsgiGraphQLHttpServletSpec.groovy +++ b/graphql-java-servlet/src/test/groovy/graphql/kickstart/servlet/OsgiGraphQLHttpServletSpec.groovy @@ -265,6 +265,43 @@ class OsgiGraphQLHttpServletSpec extends Specification { null == servlet.configuration.invocationInputFactory.schemaProvider.schema.getType("Upload") } + static class TestDirectiveProvider implements GraphQLDirectiveProvider { + @Override + Set getDirectives() { + return new HashSet<>(Arrays.asList(GraphQLDirective.newDirective().name("myDirective").build())); + } + } + + def "directive provider adds directives"() { + setup: + OsgiGraphQLHttpServlet servlet = new OsgiGraphQLHttpServlet() + TestDirectiveProvider directiveProvider = new TestDirectiveProvider() + + when: + servlet.bindDirectivesProvider(directiveProvider) + + then: + def directive = servlet.configuration.invocationInputFactory.schemaProvider.schema.getDirective("myDirective") + directive != null + directive.name == "myDirective" + + when: + servlet.unbindDirectivesProvider(directiveProvider) + + then: + null == servlet.configuration.invocationInputFactory.schemaProvider.schema.getDirective("myDirective") + + when: + servlet.bindProvider(directiveProvider) + then: + servlet.configuration.invocationInputFactory.schemaProvider.schema.getDirective("myDirective").name == "myDirective" + + when: + servlet.unbindProvider(directiveProvider) + then: + null == servlet.configuration.invocationInputFactory.schemaProvider.schema.getType("myDirective") + } + def "servlet listener is bound and unbound"() { setup: def servlet = new OsgiGraphQLHttpServlet()