diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java index 0f6e67c10..906b646a9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java @@ -22,7 +22,9 @@ import java.util.Map; import org.springframework.batch.item.data.MongoItemReader; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.Query; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * A builder implementation for the {@link MongoItemReader} @@ -34,7 +36,7 @@ import org.springframework.util.Assert; public class MongoItemReaderBuilder { private MongoOperations template; - private String query; + private String jsonQuery; private Class targetType; @@ -58,6 +60,8 @@ public class MongoItemReaderBuilder { private int currentItemCount; + private Query query; + /** * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} @@ -129,16 +133,16 @@ public class MongoItemReaderBuilder { } /** - * A JSON formatted MongoDB query. Parameterization of the provided query is allowed + * A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is allowed * via ?<index> placeholders where the <index> indicates the index of the * parameterValue to substitute. * - * @param query JSON formatted Mongo query + * @param query JSON formatted Mongo jsonQuery * @return The current instance of the builder * @see MongoItemReader#setQuery(String) */ - public MongoItemReaderBuilder query(String query) { - this.query = query; + public MongoItemReaderBuilder jsonQuery(String query) { + this.jsonQuery = query; return this; } @@ -237,6 +241,20 @@ public class MongoItemReaderBuilder { return this; } + /** + * Provide a Spring Data Mongo {@link Query}. This will take precidence over a JSON + * configured query. + * + * @param query Query to execute + * @return this instance for method chaining + * @see MongoItemReader#setQuery(Query) + */ + public MongoItemReaderBuilder query(Query query) { + this.query = query; + + return this; + } + /** * Validates and builds a {@link MongoItemReader}. * @@ -248,18 +266,25 @@ public class MongoItemReaderBuilder { Assert.hasText(this.name, "A name is required when saveState is set to true"); } Assert.notNull(this.targetType, "targetType is required."); - Assert.notNull(this.query, "query is required."); - Assert.notNull(this.sorts, "sorts map is required."); + Assert.state(StringUtils.hasText(this.jsonQuery) || this.query != null, "A query is required"); + + if(StringUtils.hasText(this.jsonQuery)) { + Assert.notNull(this.sorts, "sorts map is required."); + } + else { + Assert.state(this.query.getLimit() != 0, "PageSize in Query object was ignored."); + } MongoItemReader reader = new MongoItemReader<>(); reader.setTemplate(this.template); reader.setTargetType(this.targetType); - reader.setQuery(this.query); + reader.setQuery(this.jsonQuery); reader.setSort(this.sorts); reader.setHint(this.hint); reader.setFields(this.fields); reader.setCollection(this.collection); reader.setParameterValues(this.parameterValues); + reader.setQuery(this.query); reader.setPageSize(this.pageSize); reader.setName(this.name); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java index 7dca98804..31f59774a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java @@ -106,7 +106,7 @@ public class MongoItemReaderBuilderTests { public void testCollection() throws Exception { MongoItemReader reader = getBasicBuilder() .parameterValues(Collections.singletonList("foo")) - .query("{ name : ?0 }") + .jsonQuery("{ name : ?0 }") .collection("collection") .build(); @@ -126,7 +126,7 @@ public class MongoItemReaderBuilderTests { @Test public void testNullTemplate() { validateExceptionMessage(new MongoItemReaderBuilder().targetType(String.class) - .query("{ }") + .jsonQuery("{ }") .sorts(this.sortOptions) .name("mongoReaderTest") .pageSize(50), "template is required."); @@ -135,7 +135,7 @@ public class MongoItemReaderBuilderTests { @Test public void testNullTargetType() { validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .query("{ }") + .jsonQuery("{ }") .sorts(this.sortOptions) .name("mongoReaderTest") .pageSize(50), "targetType is required."); @@ -147,14 +147,14 @@ public class MongoItemReaderBuilderTests { .targetType(String.class) .sorts(this.sortOptions) .name("mongoReaderTest") - .pageSize(50), "query is required."); + .pageSize(50), "A query is required"); } @Test public void testNullSorts() { validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) .targetType(String.class) - .query("{ }") + .jsonQuery("{ }") .name("mongoReaderTest") .pageSize(50), "sorts map is required."); } @@ -163,7 +163,7 @@ public class MongoItemReaderBuilderTests { public void testNullName() { validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) .targetType(String.class) - .query("{ }") + .jsonQuery("{ }") .sorts(this.sortOptions) .pageSize(50), "A name is required when saveState is set to true"); } @@ -171,18 +171,22 @@ public class MongoItemReaderBuilderTests { private void validateExceptionMessage(MongoItemReaderBuilder builder, String message) { try { builder.build(); - fail("IllegalArgumentException should have been thrown"); + fail("Exception should have been thrown"); } catch (IllegalArgumentException iae) { assertEquals("IllegalArgumentException message did not match the expected result.", message, iae.getMessage()); } + catch (IllegalStateException ise) { + assertEquals("IllegalStateException message did not match the expected result.", message, + ise.getMessage()); + } } private MongoItemReaderBuilder getBasicBuilder() { return new MongoItemReaderBuilder().template(this.template) .targetType(String.class) - .query("{ }") + .jsonQuery("{ }") .sorts(this.sortOptions) .name("mongoReaderTest") .pageSize(50);