diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/QueryByExampleDataFetcher.java b/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/QueryByExampleDataFetcher.java
index fe397dac..970c8dbd 100644
--- a/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/QueryByExampleDataFetcher.java
+++ b/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/QueryByExampleDataFetcher.java
@@ -45,7 +45,6 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.MergedAnnotations;
-import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
@@ -87,35 +86,65 @@ import org.springframework.util.StringUtils;
* wiring.dataFetcher("book", QueryByExampleDataFetcher.builder(repository).single());
*
*
- *
See methods on {@link QueryByExampleDataFetcher.Builder} and {@link QueryByExampleDataFetcher.ReactiveBuilder} for further
- * options on GraphQL Query argument to Query by Example bindings, result projections, and sorting.
+ *
See methods on {@link QueryByExampleDataFetcher.Builder} and
+ * {@link QueryByExampleDataFetcher.ReactiveBuilder} for further options on
+ * GraphQL Query argument to Query by Example bindings, result projections, and
+ * sorting.
*
* @param returned result type
* @author Greg Turnquist
+ * @since 1.0.0
+ *
* @see QueryByExampleExecutor
* @see ReactiveQueryByExampleExecutor
* @see Example
* @see
* Spring Data Query By Example extension
- * @since 1.0.0
*/
public abstract class QueryByExampleDataFetcher {
private final TypeInformation domainType;
- private GraphQlArgumentInstantiator instantiator;
+ private final GraphQlArgumentInstantiator instantiator;
- QueryByExampleDataFetcher(TypeInformation domainType, @Nullable ConversionService conversionService) {
+
+ QueryByExampleDataFetcher(TypeInformation domainType) {
this.domainType = domainType;
- this.instantiator = new GraphQlArgumentInstantiator(conversionService);
+ this.instantiator = new GraphQlArgumentInstantiator(null);
}
+
+ /**
+ * Prepare an {@link Example} from GraphQL query arguments.
+ * @param env contextual info for the GraphQL query
+ * @return the resulting example
+ */
+ protected Example buildExample(DataFetchingEnvironment env) {
+ return Example.of(this.instantiator.instantiate(env.getArguments(), this.domainType.getType()));
+ }
+
+ protected boolean requiresProjection(Class> resultType) {
+ return !resultType.equals(this.domainType.getType());
+ }
+
+ protected Collection buildPropertyPaths(DataFetchingFieldSelectionSet selection, Class> resultType) {
+
+ // Compute selection only for non-projections
+ if (this.domainType.getType().equals(resultType) ||
+ this.domainType.getType().isAssignableFrom(resultType) ||
+ this.domainType.isSubTypeOf(resultType)) {
+ return PropertySelection.create(this.domainType, selection).toList();
+ }
+ return Collections.emptyList();
+ }
+
+
/**
* Create a new {@link Builder} accepting {@link QueryByExampleExecutor}
* to build a {@link DataFetcher}.
*
- * @param executor the repository object to use
- * @param result type
+ * @param executor the QBE repository object to use
+ * @param the domain type of the repository
* @return a new builder
*/
public static Builder builder(QueryByExampleExecutor executor) {
@@ -124,10 +153,10 @@ public abstract class QueryByExampleDataFetcher {
/**
* Create a new {@link ReactiveBuilder} accepting
- * {@link ReactiveQueryByExampleExecutor} to build a reactive {@link DataFetcher}.
+ * {@link ReactiveQueryByExampleExecutor} to build a {@link DataFetcher}.
*
- * @param executor the repository object to use
- * @param result type
+ * @param executor the QBE repository object to use
+ * @param the domain type of the repository
* @return a new builder
*/
public static ReactiveBuilder builder(ReactiveQueryByExampleExecutor executor) {
@@ -177,31 +206,6 @@ public abstract class QueryByExampleDataFetcher {
String.format("Cannot resolve repository interface from %s", executor));
}
- /**
- * Prepare an {@link Example} from GraphQL query arguments.
- *
- * @param environment contextual info for the GraphQL query
- * @return the resulting example
- */
- @SuppressWarnings({"unchecked", "rawtypes"})
- protected Example buildExample(DataFetchingEnvironment environment) {
- return Example.of(instantiator.instantiate(environment.getArguments(), domainType.getType()));
- }
-
- protected boolean requiresProjection(Class> resultType) {
- return !resultType.equals(this.domainType.getType());
- }
-
- protected Collection buildPropertyPaths(DataFetchingFieldSelectionSet selection, Class> resultType) {
-
- // Compute selection only for non-projections
- if (this.domainType.getType().equals(resultType) ||
- this.domainType.getType().isAssignableFrom(resultType) ||
- this.domainType.isSubTypeOf(resultType)) {
- return PropertySelection.create(this.domainType, selection).toList();
- }
- return Collections.emptyList();
- }
/**
* Builder for a Query by Example-based {@link DataFetcher}. Note that builder
@@ -221,78 +225,64 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
- private final ConversionService conversionService;
-
@SuppressWarnings("unchecked")
Builder(QueryByExampleExecutor executor, Class domainType) {
- this(executor,
- ClassTypeInformation.from((Class) domainType),
- domainType,
- Sort.unsorted(),
- null);
+ this(executor, ClassTypeInformation.from((Class) domainType), domainType, Sort.unsorted());
}
- Builder(QueryByExampleExecutor executor, ClassTypeInformation domainType, Class resultType, Sort sort, ConversionService conversionService) {
+ Builder(QueryByExampleExecutor executor, ClassTypeInformation domainType, Class resultType, Sort sort) {
this.executor = executor;
this.domainType = domainType;
this.resultType = resultType;
this.sort = sort;
- this.conversionService = conversionService;
}
/**
* Project results returned from the {@link QueryByExampleExecutor}
* into the target {@code projectionType}. Projection types can be
- * either interfaces declaring getters for properties to expose or
- * regular classes outside the entity type hierarchy for
- * DTO projection.
- *
+ * either interfaces with property getters to expose or regular classes
+ * outside the entity type hierarchy for DTO projections.
* @param projectionType projection type
* @return a new {@link Builder} instance with all previously
* configured options and {@code projectionType} applied
*/
public Builder projectAs(Class projectionType) {
Assert.notNull(projectionType, "Projection type must not be null");
- return new Builder<>(this.executor, this.domainType, projectionType, this.sort, this.conversionService);
+ return new Builder<>(this.executor, this.domainType, projectionType, this.sort);
}
/**
* Apply a {@link Sort} order.
- *
* @param sort the default sort order
* @return a new {@link Builder} instance with all previously configured
* options and {@code Sort} applied
*/
public Builder sortBy(Sort sort) {
Assert.notNull(sort, "Sort must not be null");
- return new Builder<>(this.executor, this.domainType, this.resultType, sort, this.conversionService);
+ return new Builder<>(this.executor, this.domainType, this.resultType, sort);
}
/**
* Build a {@link DataFetcher} to fetch single object instances.
- *
- * @return a {@link DataFetcher} based on Query by Example to fetch one object
*/
public DataFetcher single() {
- return new SingleEntityFetcher<>(
- this.executor, this.domainType, this.resultType, this.sort, this.conversionService);
+ return new SingleEntityFetcher<>(this.executor, this.domainType, this.resultType, this.sort);
}
/**
* Build a {@link DataFetcher} to fetch many object instances.
- *
- * @return a {@link DataFetcher} based on Query Example to fetch many objects
*/
public DataFetcher> many() {
- return new ManyEntityFetcher<>(
- this.executor, this.domainType, this.resultType, this.sort, this.conversionService);
+ return new ManyEntityFetcher<>(this.executor, this.domainType, this.resultType, this.sort);
}
+
}
+
/**
- * Builder for a reactive Query by Example-based {@link DataFetcher}. Note that builder
- * instances are immutable and return a new instance of the builder when
- * calling configuration methods.
+ * Builder for a reactive Query by Example-based {@link DataFetcher}.
+ * Note that builder instances are immutable and return a new instance of
+ * the builder when calling configuration methods.
*
* @param domain type
* @param result type
@@ -307,78 +297,63 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
- private final ConversionService conversionService;
-
@SuppressWarnings("unchecked")
ReactiveBuilder(ReactiveQueryByExampleExecutor executor, Class domainType) {
- this(executor,
- ClassTypeInformation.from((Class) domainType),
- domainType,
- Sort.unsorted(),
- null);
+ this(executor, ClassTypeInformation.from((Class) domainType), domainType, Sort.unsorted());
}
- ReactiveBuilder(ReactiveQueryByExampleExecutor executor,
- TypeInformation domainType,
- Class resultType,
- Sort sort,
- ConversionService conversionService) {
+ ReactiveBuilder(
+ ReactiveQueryByExampleExecutor executor, TypeInformation domainType,
+ Class resultType, Sort sort) {
+
this.executor = executor;
this.domainType = domainType;
this.resultType = resultType;
this.sort = sort;
- this.conversionService = conversionService;
}
/**
- * Project results returned from the {@link QueryByExampleExecutor}
+ * Project results returned from the {@link ReactiveQueryByExampleExecutor}
* into the target {@code projectionType}. Projection types can be
- * either interfaces declaring getters for properties to expose or
- * regular classes outside the entity type hierarchy for
- * DTO projection.
- *
+ * either interfaces with property getters to expose or regular classes
+ * outside the entity type hierarchy for DTO projections.
* @param projectionType projection type
* @return a new {@link ReactiveBuilder} instance with all previously
* configured options and {@code projectionType} applied
*/
public ReactiveBuilder projectAs(Class projectionType) {
Assert.notNull(projectionType, "Projection type must not be null");
- return new ReactiveBuilder<>(this.executor, this.domainType, projectionType, this.sort, this.conversionService);
+ return new ReactiveBuilder<>(this.executor, this.domainType, projectionType, this.sort);
}
/**
* Apply a {@link Sort} order.
- *
* @param sort the default sort order
* @return a new {@link ReactiveBuilder} instance with all previously configured
* options and {@code Sort} applied
*/
public ReactiveBuilder sortBy(Sort sort) {
Assert.notNull(sort, "Sort must not be null");
- return new ReactiveBuilder<>(this.executor, this.domainType, this.resultType, sort, this.conversionService);
+ return new ReactiveBuilder<>(this.executor, this.domainType, this.resultType, sort);
}
/**
- * Build a {@link DataFetcher} to fetch single object instances through {@link Mono}.
- *
- * @return a {@link DataFetcher} based on Query by Example to fetch one object
+ * Build a {@link DataFetcher} to fetch single object instances.
*/
public DataFetcher> single() {
- return new ReactiveSingleEntityFetcher<>(
- this.executor, this.domainType, this.resultType, this.sort, this.conversionService);
+ return new ReactiveSingleEntityFetcher<>(this.executor, this.domainType, this.resultType, this.sort);
}
/**
- * Build a {@link DataFetcher} to fetch many object instances through {@link Flux}.
- *
- * @return a {@link DataFetcher} based on Query by Example to fetch many objects
+ * Build a {@link DataFetcher} to fetch many object instances.
*/
public DataFetcher> many() {
- return new ReactiveManyEntityFetcher<>(
- this.executor, this.domainType, this.resultType, this.sort, this.conversionService);
+ return new ReactiveManyEntityFetcher<>(this.executor, this.domainType, this.resultType, this.sort);
}
+
}
+
private static class SingleEntityFetcher extends QueryByExampleDataFetcher implements DataFetcher {
private final QueryByExampleExecutor executor;
@@ -388,13 +363,10 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
@SuppressWarnings({"unchecked", "rawtypes"})
- SingleEntityFetcher(QueryByExampleExecutor executor,
- TypeInformation domainType,
- Class resultType,
- Sort sort,
- ConversionService conversionService) {
+ SingleEntityFetcher(
+ QueryByExampleExecutor executor, TypeInformation domainType, Class resultType, Sort sort) {
- super(domainType, conversionService);
+ super(domainType);
this.executor = executor;
this.resultType = resultType;
this.sort = sort;
@@ -424,6 +396,7 @@ public abstract class QueryByExampleDataFetcher {
}
+
private static class ManyEntityFetcher extends QueryByExampleDataFetcher implements DataFetcher> {
private final QueryByExampleExecutor executor;
@@ -433,12 +406,11 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
@SuppressWarnings({"unchecked", "rawtypes"})
- ManyEntityFetcher(QueryByExampleExecutor executor,
- TypeInformation domainType,
- Class resultType,
- Sort sort,
- ConversionService conversionService) {
- super(domainType, conversionService);
+ ManyEntityFetcher(
+ QueryByExampleExecutor executor, TypeInformation domainType,
+ Class resultType, Sort sort) {
+
+ super(domainType);
this.executor = executor;
this.resultType = resultType;
this.sort = sort;
@@ -467,6 +439,7 @@ public abstract class QueryByExampleDataFetcher {
}
+
private static class ReactiveSingleEntityFetcher extends QueryByExampleDataFetcher implements DataFetcher> {
private final ReactiveQueryByExampleExecutor executor;
@@ -476,13 +449,11 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
@SuppressWarnings({"unchecked", "rawtypes"})
- ReactiveSingleEntityFetcher(ReactiveQueryByExampleExecutor executor,
- TypeInformation domainType,
- Class resultType,
- Sort sort,
- ConversionService conversionService) {
+ ReactiveSingleEntityFetcher(
+ ReactiveQueryByExampleExecutor executor, TypeInformation domainType,
+ Class resultType, Sort sort) {
- super(domainType, conversionService);
+ super(domainType);
this.executor = executor;
this.resultType = resultType;
this.sort = sort;
@@ -511,6 +482,7 @@ public abstract class QueryByExampleDataFetcher {
}
+
private static class ReactiveManyEntityFetcher extends QueryByExampleDataFetcher implements DataFetcher> {
private final ReactiveQueryByExampleExecutor executor;
@@ -520,13 +492,11 @@ public abstract class QueryByExampleDataFetcher {
private final Sort sort;
@SuppressWarnings({"unchecked", "rawtypes"})
- ReactiveManyEntityFetcher(ReactiveQueryByExampleExecutor executor,
- TypeInformation domainType,
- Class resultType,
- Sort sort,
- ConversionService conversionService) {
+ ReactiveManyEntityFetcher(
+ ReactiveQueryByExampleExecutor executor, TypeInformation domainType,
+ Class resultType, Sort sort) {
- super(domainType, conversionService);
+ super(domainType);
this.executor = executor;
this.resultType = resultType;
this.sort = sort;
@@ -552,8 +522,10 @@ public abstract class QueryByExampleDataFetcher {
return queryToUse.all();
});
}
+
}
+
/**
* GraphQLTypeVisitor that auto-registers Query By Example Spring Data repositories.
*/
@@ -659,4 +631,5 @@ public abstract class QueryByExampleDataFetcher {
return (fetcher != null && !(fetcher instanceof PropertyDataFetcher));
}
}
+
}
diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/package-info.java b/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/package-info.java
index 6b1a7652..869707d3 100644
--- a/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/package-info.java
+++ b/spring-graphql/src/main/java/org/springframework/graphql/data/querybyexample/package-info.java
@@ -15,8 +15,11 @@
*/
/**
- * Support for {@link graphql.schema.DataFetcher}s backed by Querydsl based
- * Spring Data repositories.
+ * {@link graphql.schema.DataFetcher} implementations built on the Spring Data,
+ * Query by Example support.
+ *
+ * @see
+ * Spring Data Query By Example extension
*/
@NonNullApi
@NonNullFields
diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/QuerydslDataFetcher.java b/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/QuerydslDataFetcher.java
index 446aacc4..a022eec8 100644
--- a/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/QuerydslDataFetcher.java
+++ b/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/QuerydslDataFetcher.java
@@ -49,6 +49,7 @@ import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
+import org.springframework.data.repository.query.QueryByExampleExecutor;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.graphql.data.GraphQlRepository;
@@ -255,11 +256,10 @@ public abstract class QuerydslDataFetcher {
}
/**
- * Project results returned from the {@link QuerydslPredicateExecutor}
+ * Project results returned from the {@link QueryByExampleExecutor}
* into the target {@code projectionType}. Projection types can be
- * either interfaces declaring getters for properties to expose or
- * regular classes outside the entity type hierarchy for
- * DTO projection.
+ * either interfaces with property getters to expose or regular classes
+ * outside the entity type hierarchy for DTO projections.
* @param projectionType projection type
* @return a new {@link Builder} instance with all previously
* configured options and {@code projectionType} applied
@@ -293,7 +293,6 @@ public abstract class QuerydslDataFetcher {
/**
* Build a {@link DataFetcher} to fetch single object instances.
- * @return a {@link DataFetcher} based on Querydsl to fetch one object
*/
public DataFetcher single() {
return new SingleEntityFetcher<>(
@@ -302,7 +301,6 @@ public abstract class QuerydslDataFetcher {
/**
* Build a {@link DataFetcher} to fetch many object instances.
- * @return a {@link DataFetcher} based on Querydsl to fetch many objects
*/
public DataFetcher> many() {
return new ManyEntityFetcher<>(
@@ -354,11 +352,10 @@ public abstract class QuerydslDataFetcher {
}
/**
- * Project results returned from the {@link QuerydslPredicateExecutor}
+ * Project results returned from the {@link ReactiveQueryByExampleExecutor}
* into the target {@code projectionType}. Projection types can be
- * either interfaces declaring getters for properties to expose or
- * regular classes outside the entity type hierarchy for
- * DTO projection.
+ * either interfaces with property getters to expose or regular classes
+ * outside the entity type hierarchy for DTO projections.
* @param projectionType projection type
* @return a new {@link Builder} instance with all previously
* configured options and {@code projectionType} applied
@@ -391,8 +388,7 @@ public abstract class QuerydslDataFetcher {
}
/**
- * Build a {@link DataFetcher} to fetch single object instances through {@link Mono}.
- * @return a {@link DataFetcher} based on Querydsl to fetch one object
+ * Build a {@link DataFetcher} to fetch single object instances}.
*/
public DataFetcher> single() {
return new ReactiveSingleEntityFetcher<>(
@@ -400,8 +396,7 @@ public abstract class QuerydslDataFetcher {
}
/**
- * Build a {@link DataFetcher} to fetch many object instances through {@link Flux}.
- * @return a {@link DataFetcher} based on Querydsl to fetch many objects
+ * Build a {@link DataFetcher} to fetch many object instances.
*/
public DataFetcher> many() {
return new ReactiveManyEntityFetcher<>(
diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/package-info.java b/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/package-info.java
index 40193a5c..512bbbdd 100644
--- a/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/package-info.java
+++ b/spring-graphql/src/main/java/org/springframework/graphql/data/querydsl/package-info.java
@@ -15,8 +15,11 @@
*/
/**
- * Support for {@link graphql.schema.DataFetcher}s backed by Querydsl based
- * Spring Data repositories.
+ * {@link graphql.schema.DataFetcher} implementations built on Querydsl, Spring
+ * Data repositories.
+ *
+ * @see
+ * Spring Data Querydsl extension
*/
@NonNullApi
@NonNullFields
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookRepository.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookJpaRepository.java
similarity index 74%
rename from spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookRepository.java
rename to spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookJpaRepository.java
index 62d8cc7b..9fbb8576 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookRepository.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/BookJpaRepository.java
@@ -4,5 +4,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.graphql.data.GraphQlRepository;
@GraphQlRepository
-public interface BookRepository extends JpaRepository {
+public interface BookJpaRepository extends JpaRepository {
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/QueryByExampleDataFetcherJpaTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/QueryByExampleDataFetcherJpaTests.java
index 22ec804e..bacf0048 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/QueryByExampleDataFetcherJpaTests.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/jpa/QueryByExampleDataFetcherJpaTests.java
@@ -70,27 +70,8 @@ import static org.mockito.Mockito.when;
class QueryByExampleDataFetcherJpaTests {
@Autowired
- private BookRepository repository;
+ private BookJpaRepository repository;
- static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
- return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
- }
-
- static GraphQlSetup graphQlSetup(@Nullable QueryByExampleExecutor> executor) {
- return initGraphQlSetup(executor);
- }
-
- private static GraphQlSetup initGraphQlSetup(
- @Nullable QueryByExampleExecutor> executor) {
-
- GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
- executor != null
- ? Collections.singletonList(executor)
- : Collections.emptyList(),
- Collections.emptyList());
-
- return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
- }
@Test
void shouldFetchSingleItems() {
@@ -137,7 +118,7 @@ class QueryByExampleDataFetcherJpaTests {
@Test
void shouldFavorExplicitWiring() {
- BookRepository mockRepository = mock(BookRepository.class);
+ BookJpaRepository mockRepository = mock(BookJpaRepository.class);
Book book = new Book(42L, "Hitchhiker's Guide to the Galaxy", new Author(0L, "Douglas", "Adams"));
when(mockRepository.findBy(any(), any())).thenReturn(Optional.of(book));
@@ -188,6 +169,23 @@ class QueryByExampleDataFetcherJpaTests {
assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy");
}
+ private static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
+ return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
+ }
+
+ private static GraphQlSetup graphQlSetup(@Nullable QueryByExampleExecutor> executor) {
+ return initGraphQlSetup(executor);
+ }
+
+ private static GraphQlSetup initGraphQlSetup(@Nullable QueryByExampleExecutor> executor) {
+
+ GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
+ executor != null ? Collections.singletonList(executor) : Collections.emptyList(),
+ Collections.emptyList());
+
+ return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
+ }
+
private WebInput input(String query) {
return new WebInput(URI.create("/"), new HttpHeaders(), Collections.singletonMap("query", query), null, "1");
}
@@ -200,6 +198,7 @@ class QueryByExampleDataFetcherJpaTests {
}
+
static class BookDto {
private final String name;
@@ -214,6 +213,7 @@ class QueryByExampleDataFetcherJpaTests {
}
+
@Configuration
@EnableJpaRepositories(considerNestedRepositories = true)
static class TestConfig {
@@ -246,4 +246,5 @@ class QueryByExampleDataFetcherJpaTests {
return transactionManager;
}
}
+
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookRepository.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookMongoRepository.java
similarity index 73%
rename from spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookRepository.java
rename to spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookMongoRepository.java
index 3e731fc4..a987b91b 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookRepository.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookMongoRepository.java
@@ -4,5 +4,5 @@ import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.graphql.data.GraphQlRepository;
@GraphQlRepository
-public interface BookRepository extends MongoRepository {
+public interface BookMongoRepository extends MongoRepository {
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/ReactiveBookRepository.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookReactiveMongoRepository.java
similarity index 70%
rename from spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/ReactiveBookRepository.java
rename to spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookReactiveMongoRepository.java
index e901e741..f4d8fc12 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/ReactiveBookRepository.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/BookReactiveMongoRepository.java
@@ -4,5 +4,5 @@ import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.graphql.data.GraphQlRepository;
@GraphQlRepository
-public interface ReactiveBookRepository extends ReactiveMongoRepository {
+public interface BookReactiveMongoRepository extends ReactiveMongoRepository {
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherMongoDbTests.java
index b6a9e7f8..00ee0d33 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherMongoDbTests.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherMongoDbTests.java
@@ -64,32 +64,15 @@ import static org.mockito.Mockito.when;
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
-@Testcontainers
+@Testcontainers(disabledWithoutDocker = true)
class QueryByExampleDataFetcherMongoDbTests {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
@Autowired
- private BookRepository repository;
+ private BookMongoRepository repository;
- static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
- return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
- }
-
- static GraphQlSetup graphQlSetup(@Nullable QueryByExampleExecutor> executor) {
- return initGraphQlSetup(executor);
- }
-
- private static GraphQlSetup initGraphQlSetup(
- @Nullable QueryByExampleExecutor> executor) {
-
- GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
- (executor != null ? Collections.singletonList(executor) : Collections.emptyList()),
- Collections.emptyList());
-
- return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
- }
@Test
void shouldFetchSingleItems() {
@@ -134,7 +117,7 @@ class QueryByExampleDataFetcherMongoDbTests {
@Test
void shouldFavorExplicitWiring() {
- BookRepository mockRepository = mock(BookRepository.class);
+ BookMongoRepository mockRepository = mock(BookMongoRepository.class);
Book book = new Book("42", "Hitchhiker's Guide to the Galaxy", new Author("0", "Douglas", "Adams"));
when(mockRepository.findBy(any(), any())).thenReturn(Optional.of(book));
@@ -184,16 +167,35 @@ class QueryByExampleDataFetcherMongoDbTests {
assertThat(actualBook.getName()).isEqualTo("The book is: Hitchhiker's Guide to the Galaxy");
}
+ private static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
+ return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
+ }
+
+ private static GraphQlSetup graphQlSetup(@Nullable QueryByExampleExecutor> executor) {
+ return initGraphQlSetup(executor);
+ }
+
+ private static GraphQlSetup initGraphQlSetup(@Nullable QueryByExampleExecutor> executor) {
+
+ GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
+ (executor != null ? Collections.singletonList(executor) : Collections.emptyList()),
+ Collections.emptyList());
+
+ return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
+ }
+
private WebInput input(String query) {
return new WebInput(URI.create("/"), new HttpHeaders(), Collections.singletonMap("query", query), null, "1");
}
+
interface BookProjection {
@Value("#{target.name + ' by ' + target.author.firstName + ' ' + target.author.lastName}")
String getName();
}
+
static class BookDto {
private final String name;
@@ -207,6 +209,7 @@ class QueryByExampleDataFetcherMongoDbTests {
}
}
+
@Configuration
@EnableMongoRepositories(considerNestedRepositories = true)
static class TestConfig {
@@ -215,8 +218,8 @@ class QueryByExampleDataFetcherMongoDbTests {
MongoTemplate mongoTemplate() {
return new MongoTemplate(MongoClients.create(String.format("mongodb://%s:%d",
mongoDBContainer.getContainerIpAddress(),
- mongoDBContainer.getFirstMappedPort())),
- "test");
+ mongoDBContainer.getFirstMappedPort())), "test");
}
}
+
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherReactiveMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherReactiveMongoDbTests.java
index 798a8325..c575d00e 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherReactiveMongoDbTests.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/querybyexample/mongodb/QueryByExampleDataFetcherReactiveMongoDbTests.java
@@ -60,32 +60,15 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
-@Testcontainers
+@Testcontainers(disabledWithoutDocker = true)
class QueryByExampleDataFetcherReactiveMongoDbTests {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"));
@Autowired
- private ReactiveBookRepository repository;
+ private BookReactiveMongoRepository repository;
- static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
- return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
- }
-
- static GraphQlSetup graphQlSetup(@Nullable ReactiveQueryByExampleExecutor> executor) {
- return initGraphQlSetup(executor);
- }
-
- private static GraphQlSetup initGraphQlSetup(
- @Nullable ReactiveQueryByExampleExecutor> reactiveExecutor) {
-
- GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
- Collections.emptyList(),
- (reactiveExecutor != null ? Collections.singletonList(reactiveExecutor) : Collections.emptyList()));
-
- return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
- }
@Test
void shouldReactivelyFetchSingleItems() {
@@ -156,16 +139,36 @@ class QueryByExampleDataFetcherReactiveMongoDbTests {
tester.accept(graphQlSetup(repository));
}
+ private static GraphQlSetup graphQlSetup(String fieldName, DataFetcher> fetcher) {
+ return initGraphQlSetup(null).queryFetcher(fieldName, fetcher);
+ }
+
+ private static GraphQlSetup graphQlSetup(@Nullable ReactiveQueryByExampleExecutor> executor) {
+ return initGraphQlSetup(executor);
+ }
+
+ private static GraphQlSetup initGraphQlSetup(@Nullable ReactiveQueryByExampleExecutor> executor) {
+
+ GraphQLTypeVisitor visitor = QueryByExampleDataFetcher.registrationTypeVisitor(
+ Collections.emptyList(),
+ (executor != null ? Collections.singletonList(executor) : Collections.emptyList()));
+
+ return GraphQlSetup.schemaResource(BookSource.schema).typeVisitor(visitor);
+ }
+
private WebInput input(String query) {
return new WebInput(URI.create("/"), new HttpHeaders(), Collections.singletonMap("query", query), null, "1");
}
+
interface BookProjection {
@Value("#{target.name + ' by ' + target.author.firstName + ' ' + target.author.lastName}")
String getName();
+
}
+
static class BookDto {
private final String name;
@@ -177,8 +180,10 @@ class QueryByExampleDataFetcherReactiveMongoDbTests {
public String getName() {
return "The book is: " + name;
}
+
}
+
@Configuration
@EnableReactiveMongoRepositories(considerNestedRepositories = true)
static class TestConfig {
@@ -190,5 +195,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests {
mongoDBContainer.getFirstMappedPort())),
"test");
}
+
}
+
}