diff --git a/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLJpaQueryGraphQlSourceAutoConfiguration.java b/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLJpaQueryGraphQlSourceAutoConfiguration.java index 29b56b0bb..3e33b86eb 100644 --- a/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLJpaQueryGraphQlSourceAutoConfiguration.java +++ b/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLJpaQueryGraphQlSourceAutoConfiguration.java @@ -15,9 +15,11 @@ */ package com.introproventures.graphql.jpa.query.autoconfigure; +import com.introproventures.graphql.jpa.query.schema.JavaScalarsWiringPostProcessor; import graphql.GraphQL; import graphql.execution.instrumentation.Instrumentation; import graphql.schema.GraphQLSchema; +import java.util.List; import java.util.function.Consumer; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectProvider; @@ -113,4 +115,12 @@ public GraphQlSource graphQlSource( public JavaScalarsRuntimeWiringConfigurer javaScalarsRuntimeWiringConfigurer() { return new JavaScalarsRuntimeWiringConfigurer(); } + + @Bean + @ConditionalOnMissingBean + public GraphQlSourceBuilderCustomizer javaScalarGraphQlSourceBuilderCustomizer() { + return customizer -> { + customizer.typeVisitorsToTransformSchema(List.of(new JavaScalarsWiringPostProcessor.Visitor())); + }; + } } diff --git a/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/JavaScalarsRuntimeWiringConfigurer.java b/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/JavaScalarsRuntimeWiringConfigurer.java index 422e0194f..0cc7fa61d 100644 --- a/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/JavaScalarsRuntimeWiringConfigurer.java +++ b/autoconfigure/src/main/java/com/introproventures/graphql/jpa/query/autoconfigure/JavaScalarsRuntimeWiringConfigurer.java @@ -1,7 +1,6 @@ package com.introproventures.graphql.jpa.query.autoconfigure; import com.introproventures.graphql.jpa.query.schema.JavaScalars; -import com.introproventures.graphql.jpa.query.schema.JavaScalarsWiringPostProcessor; import graphql.schema.idl.RuntimeWiring; import org.springframework.graphql.execution.RuntimeWiringConfigurer; @@ -10,7 +9,5 @@ public class JavaScalarsRuntimeWiringConfigurer implements RuntimeWiringConfigur @Override public void configure(RuntimeWiring.Builder wiringBuilder) { JavaScalars.scalars().forEach(wiringBuilder::scalar); - - wiringBuilder.transformer(new JavaScalarsWiringPostProcessor()); } } diff --git a/autoconfigure/src/test/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLSchemaAutoConfigurationTest.java b/autoconfigure/src/test/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLSchemaAutoConfigurationTest.java index 6e730afec..e2f674575 100644 --- a/autoconfigure/src/test/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLSchemaAutoConfigurationTest.java +++ b/autoconfigure/src/test/java/com/introproventures/graphql/jpa/query/autoconfigure/GraphQLSchemaAutoConfigurationTest.java @@ -363,10 +363,12 @@ public void configure(GraphQLShemaRegistration registry) { .coercing(new JavaScalars.GraphQLObjectCoercing()) .build() ) - .scalar(ExtendedScalars.GraphQLLong) - .transformer(new JavaScalarsWiringPostProcessor()); + .scalar(ExtendedScalars.GraphQLLong); - registry.register(new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring.build())); + registry.register( + new JavaScalarsWiringPostProcessor() + .process(new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring.build())) + ); } } } diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 16162f795..5f6de94d0 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -14,13 +14,13 @@ </description> <properties> - <spring-boot.version>3.2.3</spring-boot.version> - <graphql-java.version>21.4</graphql-java.version> + <spring-boot.version>3.3.2</spring-boot.version> + <graphql-java.version>22.1</graphql-java.version> <evo-inflector.version>1.3</evo-inflector.version> <joda-time.version>2.12.7</joda-time.version> - <graphql-java-extended-scalars.version>21.0</graphql-java-extended-scalars.version> + <graphql-java-extended-scalars.version>22.0</graphql-java-extended-scalars.version> <jakarta.persistence-api.version>3.1.0</jakarta.persistence-api.version> - <hibernate.version>6.4.6.Final</hibernate.version> + <hibernate.version>6.5.2.Final</hibernate.version> </properties> <dependencyManagement> diff --git a/scalars/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalarsWiringPostProcessor.java b/scalars/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalarsWiringPostProcessor.java index ed9c52abd..3bfe7a06c 100644 --- a/scalars/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalarsWiringPostProcessor.java +++ b/scalars/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalarsWiringPostProcessor.java @@ -9,24 +9,22 @@ import graphql.schema.GraphQLSchemaElement; import graphql.schema.GraphQLTypeVisitorStub; import graphql.schema.SchemaTransformer; -import graphql.schema.idl.SchemaGeneratorPostProcessing; import graphql.util.TraversalControl; import graphql.util.TraverserContext; import graphql.util.TreeTransformerUtil; import java.util.function.Function; -public class JavaScalarsWiringPostProcessor implements SchemaGeneratorPostProcessing { +public class JavaScalarsWiringPostProcessor { public JavaScalarsWiringPostProcessor() {} - @Override public GraphQLSchema process(GraphQLSchema originalSchema) { Visitor visitor = new Visitor(); return SchemaTransformer.transformSchema(originalSchema, visitor); } - class Visitor extends GraphQLTypeVisitorStub { + public static class Visitor extends GraphQLTypeVisitorStub { private boolean schemaChanged = false; diff --git a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java index 29e5cbd04..243fb9d27 100644 --- a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java +++ b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContext.java @@ -24,8 +24,6 @@ import graphql.execution.ExecutionStrategy; import graphql.execution.instrumentation.ChainedInstrumentation; import graphql.execution.instrumentation.Instrumentation; -import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation; -import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions; import graphql.schema.GraphQLCodeRegistry; import graphql.schema.GraphQLSchema; import graphql.schema.visibility.GraphqlFieldVisibility; @@ -45,7 +43,6 @@ public class GraphQLJpaExecutorContext implements GraphQLExecutorContext { private final Supplier<GraphqlFieldVisibility> graphqlFieldVisibility; private final Supplier<Instrumentation> instrumentation; private final Supplier<GraphQLContext> graphqlContext; - private final Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions; private final Supplier<DataLoaderRegistry> dataLoaderRegistry; private final Supplier<ExecutionStrategy> queryExecutionStrategy; private final Supplier<ExecutionStrategy> mutationExecutionStrategy; @@ -57,7 +54,6 @@ private GraphQLJpaExecutorContext(Builder builder) { this.graphqlFieldVisibility = builder.graphqlFieldVisibility; this.instrumentation = builder.instrumentation; this.graphqlContext = builder.graphqlContext; - this.dataLoaderDispatcherInstrumentationOptions = builder.dataLoaderDispatcherInstrumentationOptions; this.dataLoaderRegistry = builder.dataLoaderRegistry; this.queryExecutionStrategy = builder.queryExecutionStrategy; this.mutationExecutionStrategy = builder.mutationExecutionStrategy; @@ -93,13 +89,7 @@ public DataLoaderRegistry newDataLoaderRegistry() { } public Instrumentation newIstrumentation() { - DataLoaderDispatcherInstrumentationOptions options = dataLoaderDispatcherInstrumentationOptions.get(); - - DataLoaderDispatcherInstrumentation dispatcherInstrumentation = new DataLoaderDispatcherInstrumentation( - options - ); - - List<Instrumentation> list = Arrays.asList(dispatcherInstrumentation, instrumentation.get()); + List<Instrumentation> list = Arrays.asList(instrumentation.get()); return new ChainedInstrumentation(list); } @@ -126,27 +116,23 @@ public interface IGraphQLSchemaStage { } public interface IBuildStage { - public IBuildStage executionInputFactory(GraphQLExecutionInputFactory executionInputFactory); + IBuildStage executionInputFactory(GraphQLExecutionInputFactory executionInputFactory); - public IBuildStage graphqlFieldVisibility(Supplier<GraphqlFieldVisibility> graphqlFieldVisibility); + IBuildStage graphqlFieldVisibility(Supplier<GraphqlFieldVisibility> graphqlFieldVisibility); - public IBuildStage instrumentation(Supplier<Instrumentation> instrumentation); + IBuildStage instrumentation(Supplier<Instrumentation> instrumentation); - public IBuildStage graphqlContext(Supplier<GraphQLContext> graphqlContext); + IBuildStage graphqlContext(Supplier<GraphQLContext> graphqlContext); - public IBuildStage dataLoaderDispatcherInstrumentationOptions( - Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions - ); + IBuildStage dataLoaderRegistry(Supplier<DataLoaderRegistry> dataLoaderRegistry); - public IBuildStage dataLoaderRegistry(Supplier<DataLoaderRegistry> dataLoaderRegistry); + IBuildStage queryExecutionStrategy(Supplier<ExecutionStrategy> queryExecutionStrategy); - public IBuildStage queryExecutionStrategy(Supplier<ExecutionStrategy> queryExecutionStrategy); + IBuildStage mutationExecutionStrategy(Supplier<ExecutionStrategy> mutationExecutionStrategy); - public IBuildStage mutationExecutionStrategy(Supplier<ExecutionStrategy> mutationExecutionStrategy); + IBuildStage subscriptionExecutionStrategy(Supplier<ExecutionStrategy> subscriptionExecutionStrategy); - public IBuildStage subscriptionExecutionStrategy(Supplier<ExecutionStrategy> subscriptionExecutionStrategy); - - public GraphQLJpaExecutorContext build(); + GraphQLJpaExecutorContext build(); } /** @@ -159,7 +145,6 @@ public static final class Builder implements IGraphQLSchemaStage, IBuildStage { private Supplier<GraphqlFieldVisibility> graphqlFieldVisibility; private Supplier<Instrumentation> instrumentation; private Supplier<GraphQLContext> graphqlContext; - private Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions; private Supplier<DataLoaderRegistry> dataLoaderRegistry; private Supplier<ExecutionStrategy> queryExecutionStrategy; private Supplier<ExecutionStrategy> mutationExecutionStrategy; @@ -197,15 +182,6 @@ public IBuildStage graphqlContext(Supplier<GraphQLContext> graphqlContext) { return this; } - @Override - public IBuildStage dataLoaderDispatcherInstrumentationOptions( - Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions - ) { - this.dataLoaderDispatcherInstrumentationOptions = dataLoaderDispatcherInstrumentationOptions; - - return this; - } - @Override public IBuildStage dataLoaderRegistry(Supplier<DataLoaderRegistry> dataLoaderRegistry) { this.dataLoaderRegistry = dataLoaderRegistry; diff --git a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java index 2702d83fe..51e930526 100644 --- a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java +++ b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactory.java @@ -26,7 +26,6 @@ import graphql.execution.SubscriptionExecutionStrategy; import graphql.execution.instrumentation.Instrumentation; import graphql.execution.instrumentation.SimpleInstrumentation; -import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions; import graphql.schema.GraphQLSchema; import graphql.schema.visibility.DefaultGraphqlFieldVisibility; import graphql.schema.visibility.GraphqlFieldVisibility; @@ -45,11 +44,6 @@ public class GraphQLJpaExecutorContextFactory implements GraphQLExecutorContextF DefaultGraphqlFieldVisibility.DEFAULT_FIELD_VISIBILITY; private Supplier<Instrumentation> instrumentation = () -> new SimpleInstrumentation(); private Supplier<GraphQLContext> graphqlContext = () -> GraphQLContext.newContext().build(); - private Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions = () -> { - DataLoaderDispatcherInstrumentationOptions options = DataLoaderDispatcherInstrumentationOptions.newOptions(); - - return logger.isDebugEnabled() ? options.includeStatistics(true) : options; - }; private Supplier<DataLoaderOptions> dataLoaderOptions = () -> DataLoaderOptions.newOptions(); @@ -74,7 +68,6 @@ public GraphQLExecutorContext newExecutorContext(GraphQLSchema graphQLSchema) { .graphqlFieldVisibility(graphqlFieldVisibility) .instrumentation(instrumentation) .graphqlContext(graphqlContext) - .dataLoaderDispatcherInstrumentationOptions(dataLoaderDispatcherInstrumentationOptions) .dataLoaderRegistry(dataLoaderRegistry) .queryExecutionStrategy(queryExecutionStrategy) .mutationExecutionStrategy(mutationExecutionStrategy) @@ -106,13 +99,6 @@ public GraphQLJpaExecutorContextFactory withGraphqlContext(Supplier<GraphQLConte return this; } - public GraphQLJpaExecutorContextFactory withDataLoaderDispatcherInstrumentationOptions( - Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions - ) { - this.dataLoaderDispatcherInstrumentationOptions = dataLoaderDispatcherInstrumentationOptions; - return this; - } - public GraphQLJpaExecutorContextFactory withQueryExecutionStrategy( Supplier<ExecutionStrategy> queryExecutionStrategy ) { @@ -149,8 +135,4 @@ public Supplier<Instrumentation> getInstrumentation() { public Supplier<GraphQLContext> getGraphqlContext() { return graphqlContext; } - - public Supplier<DataLoaderDispatcherInstrumentationOptions> getDataLoaderDispatcherInstrumentationOptions() { - return dataLoaderDispatcherInstrumentationOptions; - } } diff --git a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryFactory.java b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryFactory.java index 83f8322df..7e63c1652 100644 --- a/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryFactory.java +++ b/schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryFactory.java @@ -1306,7 +1306,16 @@ protected Predicate getObjectFieldPredicate( new Field(objectField.getName()) ); - if (Arrays.asList(Logical.EXISTS, Logical.NOT_EXISTS).contains(logical)) { + List<Map<String, Object>> logicalArguments = Optional + .ofNullable(environment.getArgument(logical.name())) + .filter(List.class::isInstance) + .map(List.class::cast) + .orElseGet(List::of); + + final var isMultipleLogical = + logicalArguments.stream().filter(it -> it.containsKey(objectField.getName())).count() >= 1; + + if (Arrays.asList(Logical.EXISTS, Logical.NOT_EXISTS).contains(logical) || isMultipleLogical) { AbstractQuery<?> query = environment.getRoot(); Subquery<?> subquery = query.subquery(attribute.getJavaType()); From<?, ?> correlation = Root.class.isInstance(from) @@ -1329,28 +1338,17 @@ protected Predicate getObjectFieldPredicate( Predicate exists = cb.exists(subquery.select((Join) correlationJoin).where(restriction)); - return logical == Logical.EXISTS ? exists : cb.not(exists); + return logical == Logical.NOT_EXISTS ? cb.not(exists) : exists; } - AbstractQuery<?> query = environment.getRoot(); - Boolean isFetch = environment.getLocalContext(); - boolean isOptional = isOptionalAttribute(attribute); - List<Map<String, Object>> logicalArguments = Optional - .ofNullable(environment.getArgument(logical.name())) - .filter(List.class::isInstance) - .map(List.class::cast) - .orElseGet(List::of); + final AbstractQuery<?> query = environment.getRoot(); + final Boolean isFetch = environment.getLocalContext(); + final boolean isOptional = isOptionalAttribute(attribute); + + final From<?, ?> context = (isSubquery(query) || isCountQuery(query) || !isFetch) + ? reuseJoin(from, objectField.getName(), isOptional) + : reuseFetch(from, objectField.getName(), isOptional); - From<?, ?> context; - if (logicalArguments.stream().filter(it -> it.containsKey(objectField.getName())).count() >= 1) { - context = - isOptional ? from.join(objectField.getName(), JoinType.LEFT) : from.join(objectField.getName()); - } else { - context = - (isSubquery(query) || isCountQuery(query) || !isFetch) - ? reuseJoin(from, objectField.getName(), isOptional) - : reuseFetch(from, objectField.getName(), isOptional); - } return getArgumentPredicate( cb, context, diff --git a/schema/src/test/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactoryTest.java b/schema/src/test/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactoryTest.java index 65c30719a..825cc9032 100644 --- a/schema/src/test/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactoryTest.java +++ b/schema/src/test/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaExecutorContextFactoryTest.java @@ -192,6 +192,6 @@ public void testInstrumentationDisabled() { ExecutionResult result = executor.execute(query); // then - assertThat(result.getExtensions().get("tracing")).isNull(); + assertThat(result.getExtensions()).isNull(); } } diff --git a/tests/gatling/pom.xml b/tests/gatling/pom.xml index 0ef5875a3..751716c58 100644 --- a/tests/gatling/pom.xml +++ b/tests/gatling/pom.xml @@ -12,9 +12,10 @@ <properties> <java.version>21</java.version> - <activiti-cloud.version>8.4.0</activiti-cloud.version> + <activiti-cloud.version>8.6.0</activiti-cloud.version> <gatling.version>3.10.5</gatling.version> <gatling-maven-plugin.version>4.8.2</gatling-maven-plugin.version> + <hibernate.version>6.4.10.Final</hibernate.version> </properties> <dependencies>