diff --git a/.gitignore b/.gitignore index 52d6aeaa4..e3db71a00 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ target/ # Scala .cache-main .cache-tests + +.sts4-cache diff --git a/graphql-jpa-query-boot-starter/src/main/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfiguration.java b/graphql-jpa-query-boot-starter/src/main/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfiguration.java index 05a9ff6bf..4b7f088af 100644 --- a/graphql-jpa-query-boot-starter/src/main/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfiguration.java +++ b/graphql-jpa-query-boot-starter/src/main/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfiguration.java @@ -15,60 +15,83 @@ */ package com.introproventures.graphql.jpa.query.boot.autoconfigure; -import javax.persistence.EntityManager; +import java.util.function.Supplier; + import javax.persistence.EntityManagerFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.introproventures.graphql.jpa.query.autoconfigure.GraphQLSchemaConfigurer; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory; import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContextFactory; import com.introproventures.graphql.jpa.query.schema.GraphQLSchemaBuilder; import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutor; +import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutorContextFactory; import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSchemaBuilder; import graphql.GraphQL; +import graphql.GraphQLContext; +import graphql.execution.instrumentation.Instrumentation; import graphql.schema.GraphQLSchema; +import graphql.schema.visibility.GraphqlFieldVisibility; @Configuration @ConditionalOnClass(GraphQL.class) @ConditionalOnProperty(name="spring.graphql.jpa.query.enabled", havingValue="true", matchIfMissing=true) +@AutoConfigureAfter(HibernateJpaAutoConfiguration.class) public class GraphQLJpaQueryAutoConfiguration { - @Bean - @ConditionalOnMissingBean - @ConditionalOnSingleCandidate(EntityManagerFactory.class) - public GraphQLSchemaBuilder graphQLSchemaBuilder(final EntityManagerFactory entityManagerFactory) { - return new GraphQLJpaSchemaBuilder(entityManagerFactory.createEntityManager()); - } - - @Bean - @ConditionalOnMissingBean - public GraphQLSchemaConfigurer graphQLJpaQuerySchemaConfigurer(GraphQLSchemaBuilder graphQLSchemaBuilder) { - - return (registry) -> { - registry.register(graphQLSchemaBuilder.build()); - }; - } - @Configuration public static class DefaultGraphQLJpaQueryConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnSingleCandidate(EntityManagerFactory.class) + public GraphQLSchemaBuilder graphQLSchemaBuilder(final EntityManagerFactory entityManagerFactory) { + return new GraphQLJpaSchemaBuilder(entityManagerFactory.createEntityManager()); + } @Bean - @ConditionalOnMissingBean(GraphQLExecutor.class) - public GraphQLExecutor graphQLExecutor(GraphQLSchema graphQLSchema) { - return new GraphQLJpaExecutor(graphQLSchema); + @ConditionalOnMissingBean + public GraphQLSchemaConfigurer graphQLJpaQuerySchemaConfigurer(GraphQLSchemaBuilder graphQLSchemaBuilder) { + + return (registry) -> { + registry.register(graphQLSchemaBuilder.build()); + }; + } + + @Bean + @ConditionalOnMissingBean + public GraphQLExecutorContextFactory graphQLExecutorContextFactory(ObjectProvider graphQLExecutionInputFactory, + ObjectProvider> graphqlFieldVisibility, + ObjectProvider> instrumentation, + ObjectProvider> graphqlContext) { + GraphQLJpaExecutorContextFactory bean = new GraphQLJpaExecutorContextFactory(); + + graphQLExecutionInputFactory.ifAvailable(bean::withExecutionInputFactory); + graphqlFieldVisibility.ifAvailable(bean::withGraphqlFieldVisibility); + instrumentation.ifAvailable(bean::withInstrumentation); + graphqlContext.ifAvailable(bean::withGraphqlContext); + + return bean; } @Bean - @ConditionalOnMissingBean(GraphQLSchemaBuilder.class) - public GraphQLSchemaBuilder graphQLSchemaBuilder(final EntityManager entityManager) { - return new GraphQLJpaSchemaBuilder(entityManager); + @ConditionalOnMissingBean + public GraphQLExecutor graphQLExecutor(GraphQLSchema graphQLSchema, + GraphQLExecutorContextFactory graphQLExecutorContextFactory) { + return new GraphQLJpaExecutor(graphQLSchema, + graphQLExecutorContextFactory); } - + } } diff --git a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java similarity index 52% rename from graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java rename to graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java index 189d47c3e..285877cbe 100644 --- a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java +++ b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/boot/autoconfigure/GraphQLJpaQueryAutoConfigurationTest.java @@ -13,27 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.introproventures.graphql.jpa.query.boot.autoconfigure; +package com.introproventures.graphql.jpa.query.boot.test.boot.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; +import java.util.function.Supplier; + import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; +import com.introproventures.graphql.jpa.query.boot.test.starter.model.Author; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory; import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; import com.introproventures.graphql.jpa.query.schema.GraphQLSchemaBuilder; import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutor; +import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutorContextFactory; import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaSchemaBuilder; -import com.introproventures.graphql.jpa.query.starter.model.Author; +import graphql.GraphQLContext; +import graphql.execution.instrumentation.Instrumentation; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; +import graphql.schema.visibility.GraphqlFieldVisibility; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @@ -42,6 +51,18 @@ public class GraphQLJpaQueryAutoConfigurationTest { @SpringBootApplication @EntityScan(basePackageClasses=Author.class) static class Application { + @MockBean + private GraphQLExecutionInputFactory mockExecutionInputFactory; + + @MockBean + private Supplier mockInstrumentation; + + @MockBean + private Supplier mockGraphqlFieldVisibility; + + @MockBean + private Supplier graphqlContext; + } @Autowired(required=false) @@ -49,7 +70,22 @@ static class Application { @Autowired(required=false) private GraphQLSchemaBuilder graphQLSchemaBuilder; + + @Autowired(required=false) + private GraphQLJpaExecutorContextFactory executorContextFactory; + + @Autowired + private ObjectProvider executionInputFactory; + @Autowired + private ObjectProvider> instrumentation; + + @Autowired + private ObjectProvider> graphqlFieldVisibility; + + @Autowired + private ObjectProvider> graphqlContext; + @Autowired private GraphQLSchema graphQLSchema; @@ -61,6 +97,18 @@ public void contextIsAutoConfigured() { assertThat(graphQLSchemaBuilder).isNotNull() .isInstanceOf(GraphQLJpaSchemaBuilder.class); + assertThat(executorContextFactory).isNotNull() + .isInstanceOf(GraphQLJpaExecutorContextFactory.class); + + assertThat(executionInputFactory.getIfAvailable()).isNotNull(); + assertThat(instrumentation.getIfAvailable()).isNotNull(); + assertThat(graphqlFieldVisibility.getIfAvailable()).isNotNull(); + assertThat(graphqlContext.getIfAvailable()).isNotNull(); + + assertThat(executorContextFactory.getExecutionInputFactory()).isEqualTo(executionInputFactory.getObject()); + assertThat(executorContextFactory.getInstrumentation()).isEqualTo(instrumentation.getObject()); + assertThat(executorContextFactory.getGraphqlFieldVisibility()).isEqualTo(graphqlFieldVisibility.getObject()); + assertThat(executorContextFactory.getGraphqlContext()).isEqualTo(graphqlContext.getObject()); assertThat(graphQLSchema.getQueryType()) .extracting(GraphQLObjectType::getName, GraphQLObjectType::getDescription) diff --git a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/GraphQLJpaQueryStarterIT.java b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/GraphQLJpaQueryStarterIT.java similarity index 97% rename from graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/GraphQLJpaQueryStarterIT.java rename to graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/GraphQLJpaQueryStarterIT.java index a907e3376..ae061ba77 100644 --- a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/GraphQLJpaQueryStarterIT.java +++ b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/GraphQLJpaQueryStarterIT.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.introproventures.graphql.jpa.query.starter; +package com.introproventures.graphql.jpa.query.boot.test.starter; import static org.assertj.core.api.Assertions.assertThat; @@ -37,7 +37,7 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; -import com.introproventures.graphql.jpa.query.starter.Result.GraphQLError; +import com.introproventures.graphql.jpa.query.boot.test.starter.Result.GraphQLError; import com.introproventures.graphql.jpa.query.web.GraphQLController.GraphQLQueryRequest; @RunWith(SpringRunner.class) diff --git a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Author.java b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Author.java similarity index 92% rename from graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Author.java rename to graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Author.java index c06fd5f55..d5800ca6e 100644 --- a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Author.java +++ b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Author.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.introproventures.graphql.jpa.query.starter.model; +package com.introproventures.graphql.jpa.query.boot.test.starter.model; import java.util.Collection; diff --git a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Book.java b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Book.java similarity index 93% rename from graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Book.java rename to graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Book.java index 4e229d9ff..1dd12a722 100644 --- a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Book.java +++ b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Book.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.introproventures.graphql.jpa.query.starter.model; +package com.introproventures.graphql.jpa.query.boot.test.starter.model; import javax.persistence.Entity; import javax.persistence.EnumType; diff --git a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Genre.java b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Genre.java similarity index 90% rename from graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Genre.java rename to graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Genre.java index 675e3317a..bd1a8cb3c 100644 --- a/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/starter/model/Genre.java +++ b/graphql-jpa-query-boot-starter/src/test/java/com/introproventures/graphql/jpa/query/boot/test/starter/model/Genre.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.introproventures.graphql.jpa.query.starter.model; +package com.introproventures.graphql.jpa.query.boot.test.starter.model; public enum Genre { NOVEL, PLAY diff --git a/graphql-jpa-query-example-merge/pom.xml b/graphql-jpa-query-example-merge/pom.xml index 6972244e4..9b9117e79 100644 --- a/graphql-jpa-query-example-merge/pom.xml +++ b/graphql-jpa-query-example-merge/pom.xml @@ -32,32 +32,12 @@ com.introproventures graphql-jpa-query-example-model-starwars - - - com.introproventures - graphql-jpa-query-web - - - - com.introproventures - graphql-jpa-query-schema - com.introproventures - graphql-jpa-query-autoconfigure + graphql-jpa-query-boot-starter - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-data-jpa - - + com.h2database h2 diff --git a/graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/Application.java b/graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/Application.java index a86f19af7..5dddfe835 100644 --- a/graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/Application.java +++ b/graphql-jpa-query-example-merge/src/main/java/com/introproventures/graphql/jpa/query/example/Application.java @@ -15,13 +15,22 @@ */ package com.introproventures.graphql.jpa.query.example; -import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; -import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutor; -import graphql.schema.GraphQLSchema; +import java.util.function.Supplier; + +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.web.context.annotation.RequestScope; + +import graphql.GraphQLContext; +import graphql.execution.instrumentation.Instrumentation; +import graphql.execution.instrumentation.SimpleInstrumentation; +import graphql.execution.instrumentation.tracing.TracingInstrumentation; /** * GraphQL JPA Query Example with Spring Boot Autoconfiguration @@ -34,14 +43,28 @@ @SpringBootApplication @EnableTransactionManagement public class Application { + + private static final Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); } - + + @Bean + @RequestScope + public Supplier graphqlContext(HttpServletRequest request) { + return () -> GraphQLContext.newContext() + .of("request", request) + .of("user", request) + .build(); + } + @Bean - public GraphQLExecutor graphQLExecutor(GraphQLSchema graphQLSchema) { - return new GraphQLJpaExecutor(graphQLSchema); + @RequestScope + public Supplier instrumentation(HttpServletRequest request) { + return () -> logger.isDebugEnabled() + ? new TracingInstrumentation() + : SimpleInstrumentation.INSTANCE; } } diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutionInputFactory.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutionInputFactory.java new file mode 100644 index 000000000..2b0480aea --- /dev/null +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutionInputFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema; + +import graphql.ExecutionInput; + +public interface GraphQLExecutionInputFactory { + + default ExecutionInput.Builder create() { + return ExecutionInput.newExecutionInput(); + }; + +} diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContext.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContext.java new file mode 100644 index 000000000..54ba6b1e8 --- /dev/null +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContext.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema; + +import graphql.ExecutionInput; +import graphql.GraphQL; +import graphql.schema.GraphQLSchema; + +public interface GraphQLExecutorContext { + + ExecutionInput.Builder newExecutionInput(); + + GraphQL.Builder newGraphQL(); + + GraphQLSchema getGraphQLSchema(); + +} diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContextFactory.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContextFactory.java new file mode 100644 index 000000000..19104d733 --- /dev/null +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorContextFactory.java @@ -0,0 +1,25 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema; + +import graphql.schema.GraphQLSchema; + +public interface GraphQLExecutorContextFactory { + + GraphQLExecutorContext newExecutorContext(GraphQLSchema graphQLSchema); + +} diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutor.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutor.java index 133a5d61c..b572f044c 100644 --- a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutor.java +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutor.java @@ -24,6 +24,8 @@ import javax.transaction.Transactional.TxType; import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContext; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContextFactory; import graphql.ExecutionInput; import graphql.ExecutionResult; @@ -39,16 +41,31 @@ */ public class GraphQLJpaExecutor implements GraphQLExecutor { - private final GraphQL graphQL; + private final GraphQLSchema graphQLSchema; + private final GraphQLExecutorContextFactory contextFactory; + /** - * Creates instance using GraphQLSchema parameter. + * Creates instance using GraphQLSchema parameter with default GraphQLJpaExecutorContextFactory * * @param graphQLSchema instance */ public GraphQLJpaExecutor(GraphQLSchema graphQLSchema) { - this.graphQL = GraphQL.newGraphQL(graphQLSchema).build(); + this(graphQLSchema, new GraphQLJpaExecutorContextFactory() {}); } + + /** + * Creates instance using GraphQLSchema and GraphQLJpaExecutorContextFactory + * + * @param graphQLSchema instance + * @param GraphQLJpaExecutorContextFactory contextFactory + */ + public GraphQLJpaExecutor(GraphQLSchema graphQLSchema, + GraphQLExecutorContextFactory contextFactory) { + this.graphQLSchema = graphQLSchema; + this.contextFactory = contextFactory; + } + /* (non-Javadoc) * @see org.activiti.services.query.qraphql.jpa.QraphQLExecutor#execute(java.lang.String) @@ -67,13 +84,17 @@ public ExecutionResult execute(String query) { public ExecutionResult execute(String query, Map arguments) { Map variables = Optional.ofNullable(arguments) .orElseGet(Collections::emptyMap); - - ExecutionInput executionInput = ExecutionInput.newExecutionInput() - .query(query) - .variables(variables) - .build(); - - return graphQL.execute(executionInput); + + GraphQLExecutorContext executorContext = contextFactory.newExecutorContext(graphQLSchema); + + ExecutionInput.Builder executionInput = executorContext.newExecutionInput() + .query(query) + .variables(variables); + + GraphQL.Builder graphQL = executorContext.newGraphQL(); + + return graphQL.build() + .execute(executionInput); } } diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java new file mode 100644 index 000000000..5ec678db8 --- /dev/null +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java @@ -0,0 +1,144 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema.impl; + +import java.util.function.Supplier; + +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContext; + +import graphql.ExecutionInput; +import graphql.GraphQL; +import graphql.GraphQLContext; +import graphql.execution.instrumentation.Instrumentation; +import graphql.schema.GraphQLCodeRegistry; +import graphql.schema.GraphQLSchema; +import graphql.schema.visibility.GraphqlFieldVisibility; + +public class GraphQLJpaExecutorContext implements GraphQLExecutorContext { + + private final GraphQLSchema graphQLSchema; + private final GraphQLExecutionInputFactory executionInputFactory; + private final Supplier graphqlFieldVisibility; + private final Supplier instrumentation; + private final Supplier graphqlContext; + + private GraphQLJpaExecutorContext(Builder builder) { + this.graphQLSchema = builder.graphQLSchema; + this.executionInputFactory = builder.executionInputFactory; + this.graphqlFieldVisibility = builder.graphqlFieldVisibility; + this.instrumentation = builder.instrumentation; + this.graphqlContext = builder.graphqlContext; + } + + @Override + public ExecutionInput.Builder newExecutionInput() { + return executionInputFactory.create() + .context(graphqlContext.get()); + } + + @Override + public GraphQL.Builder newGraphQL() { + return GraphQL.newGraphQL(graphQLSchema) + .instrumentation(instrumentation.get()); + } + + @Override + public GraphQLSchema getGraphQLSchema() { + GraphQLCodeRegistry codeRegistry = graphQLSchema.getCodeRegistry() + .transform(builder -> builder.fieldVisibility(graphqlFieldVisibility.get())); + + return graphQLSchema.transform(builder -> builder.codeRegistry(codeRegistry)); + } + + /** + * Creates builder to build {@link GraphQLJpaExecutorContext}. + * @return created builder + */ + public static IGraphQLSchemaStage builder() { + return new Builder(); + } + + public interface IGraphQLSchemaStage { + + public IBuildStage graphQLSchema(GraphQLSchema graphQLSchema); + } + + public interface IBuildStage { + + public IBuildStage executionInputFactory(GraphQLExecutionInputFactory executionInputFactory); + + public IBuildStage graphqlFieldVisibility(Supplier graphqlFieldVisibility); + + public IBuildStage instrumentation(Supplier instrumentation); + + public IBuildStage graphqlContext(Supplier graphqlContext); + + public GraphQLJpaExecutorContext build(); + } + + /** + * Builder to build {@link GraphQLJpaExecutorContext}. + */ + public static final class Builder implements IGraphQLSchemaStage, IBuildStage { + + private GraphQLSchema graphQLSchema; + private GraphQLExecutionInputFactory executionInputFactory; + private Supplier graphqlFieldVisibility; + private Supplier instrumentation; + private Supplier graphqlContext; + + private Builder() { + } + + @Override + public IBuildStage graphQLSchema(GraphQLSchema graphQLSchema) { + this.graphQLSchema = graphQLSchema; + return this; + } + + @Override + public IBuildStage executionInputFactory(GraphQLExecutionInputFactory executionInputFactory) { + this.executionInputFactory = executionInputFactory; + return this; + } + + @Override + public IBuildStage graphqlFieldVisibility(Supplier graphqlFieldVisibility) { + this.graphqlFieldVisibility = graphqlFieldVisibility; + return this; + } + + @Override + public IBuildStage instrumentation(Supplier instrumentation) { + this.instrumentation = instrumentation; + return this; + } + + @Override + public IBuildStage graphqlContext(Supplier graphqlContext) { + this.graphqlContext = graphqlContext; + return this; + } + + @Override + public GraphQLJpaExecutorContext build() { + return new GraphQLJpaExecutorContext(this); + } + + } +} diff --git a/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java new file mode 100644 index 000000000..fa6aead17 --- /dev/null +++ b/graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java @@ -0,0 +1,92 @@ +/* + * Copyright 2017 IntroPro Ventures Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.introproventures.graphql.jpa.query.schema.impl; + +import java.util.function.Supplier; + +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContext; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContextFactory; + +import graphql.GraphQLContext; +import graphql.execution.instrumentation.Instrumentation; +import graphql.execution.instrumentation.SimpleInstrumentation; +import graphql.schema.GraphQLSchema; +import graphql.schema.visibility.DefaultGraphqlFieldVisibility; +import graphql.schema.visibility.GraphqlFieldVisibility; + +public class GraphQLJpaExecutorContextFactory implements GraphQLExecutorContextFactory { + + private GraphQLExecutionInputFactory executionInputFactory = new GraphQLExecutionInputFactory() {}; + private Supplier graphqlFieldVisibility = () -> DefaultGraphqlFieldVisibility.DEFAULT_FIELD_VISIBILITY; + private Supplier instrumentation = () -> new SimpleInstrumentation(); + private Supplier graphqlContext = () -> GraphQLContext.newContext().build(); + + public GraphQLJpaExecutorContextFactory() { + } + + @Override + public GraphQLExecutorContext newExecutorContext(GraphQLSchema graphQLSchema) { + return GraphQLJpaExecutorContext.builder() + .graphQLSchema(graphQLSchema) + .executionInputFactory(executionInputFactory) + .graphqlFieldVisibility(graphqlFieldVisibility) + .instrumentation(instrumentation) + .graphqlContext(graphqlContext) + .build(); + } + + public GraphQLJpaExecutorContextFactory withGraphqlFieldVisibility(Supplier graphqlFieldVisibility) { + this.graphqlFieldVisibility = graphqlFieldVisibility; + return this; + } + + + public GraphQLJpaExecutorContextFactory withInstrumentation(Supplier instrumentation) { + this.instrumentation = instrumentation; + return this; + } + + + public GraphQLJpaExecutorContextFactory withExecutionInputFactory(GraphQLExecutionInputFactory executionInputFactory) { + this.executionInputFactory = executionInputFactory; + return this; + } + + public GraphQLJpaExecutorContextFactory withGraphqlContext(Supplier graphqlContext) { + this.graphqlContext = graphqlContext; + return this; + }; + + public GraphQLExecutionInputFactory getExecutionInputFactory() { + return executionInputFactory; + } + + public Supplier getGraphqlFieldVisibility() { + return graphqlFieldVisibility; + } + + public Supplier getInstrumentation() { + return instrumentation; + } + + + public Supplier getGraphqlContext() { + return graphqlContext; + } + +} diff --git a/graphql-jpa-query-web/src/main/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfiguration.java b/graphql-jpa-query-web/src/main/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfiguration.java index ba35ad16c..82ea2945d 100644 --- a/graphql-jpa-query-web/src/main/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfiguration.java +++ b/graphql-jpa-query-web/src/main/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfiguration.java @@ -1,11 +1,13 @@ package com.introproventures.graphql.jpa.query.web.autoconfigure; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; +import com.fasterxml.jackson.databind.ObjectMapper; import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; import com.introproventures.graphql.jpa.query.web.GraphQLController; @@ -14,10 +16,18 @@ @ConditionalOnClass(GraphQLExecutor.class) @ConditionalOnProperty(prefix = "spring.graphql.jpa.query", name = {"enabled", "web.enabled"}, havingValue="true", matchIfMissing=true) public class GraphQLControllerAutoConfiguration { - - @Import(GraphQLController.class) + + @Configuration public static class DefaultGraphQLControllerConfiguration { + @Bean + @ConditionalOnMissingBean + public GraphQLController graphQLController(GraphQLExecutor graphQLExecutor, + ObjectMapper objectMapper) { + return new GraphQLController(graphQLExecutor, + objectMapper); + } + } } diff --git a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/GraphQLControllerTest.java b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/GraphQLControllerTest.java similarity index 98% rename from graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/GraphQLControllerTest.java rename to graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/GraphQLControllerTest.java index 944d7f22d..c063656f3 100644 --- a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/GraphQLControllerTest.java +++ b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/GraphQLControllerTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.introproventures.graphql.jpa.query.web; +package com.introproventures.graphql.jpa.query.test.web; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -44,6 +44,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.introproventures.graphql.jpa.query.schema.impl.GraphQLJpaExecutor; +import com.introproventures.graphql.jpa.query.web.GraphQLController; import com.introproventures.graphql.jpa.query.web.GraphQLController.GraphQLQueryRequest; import graphql.ExecutionResultImpl; diff --git a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java similarity index 94% rename from graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java rename to graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java index 3f56ff99b..6323b87e2 100644 --- a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java +++ b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationPropertyDisabledTest.java @@ -1,4 +1,4 @@ -package com.introproventures.graphql.jpa.query.web.autoconfigure; +package com.introproventures.graphql.jpa.query.test.web.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; diff --git a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java similarity index 93% rename from graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java rename to graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java index 8299c28c2..a495e7e6f 100644 --- a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java +++ b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationTest.java @@ -1,9 +1,7 @@ -package com.introproventures.graphql.jpa.query.web.autoconfigure; +package com.introproventures.graphql.jpa.query.test.web.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; -import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; -import com.introproventures.graphql.jpa.query.web.GraphQLController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -13,6 +11,9 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; +import com.introproventures.graphql.jpa.query.schema.GraphQLExecutor; +import com.introproventures.graphql.jpa.query.web.GraphQLController; + @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) public class GraphQLControllerAutoConfigurationTest { diff --git a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java similarity index 94% rename from graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java rename to graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java index 6ffa93f3f..97e22d37f 100644 --- a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java +++ b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebNoneTest.java @@ -1,4 +1,4 @@ -package com.introproventures.graphql.jpa.query.web.autoconfigure; +package com.introproventures.graphql.jpa.query.test.web.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; diff --git a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java similarity index 94% rename from graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java rename to graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java index bc248dacd..b65448e9e 100644 --- a/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java +++ b/graphql-jpa-query-web/src/test/java/com/introproventures/graphql/jpa/query/test/web/autoconfigure/GraphQLControllerAutoConfigurationWebPropertyDisabledTest.java @@ -1,4 +1,4 @@ -package com.introproventures.graphql.jpa.query.web.autoconfigure; +package com.introproventures.graphql.jpa.query.test.web.autoconfigure; import static org.assertj.core.api.Assertions.assertThat;