diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/MongoDbOutboundGatewaySpec.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/MongoDbOutboundGatewaySpec.java
index 97d99fa3d6..1e2d89131f 100644
--- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/MongoDbOutboundGatewaySpec.java
+++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/dsl/MongoDbOutboundGatewaySpec.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 the original author or authors.
+ * Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.expression.FunctionExpression;
+import org.springframework.integration.mongodb.outbound.MessageCollectionCallback;
import org.springframework.integration.mongodb.outbound.MongoDbOutboundGateway;
import org.springframework.messaging.Message;
@@ -33,6 +34,8 @@ import org.springframework.messaging.Message;
* A {@link MessageHandlerSpec} extension for the MongoDb Outbound endpoint {@link MongoDbOutboundGateway}
*
* @author Xavier Padró
+ * @author Artem Bilan
+ *
* @since 5.0
*/
public class MongoDbOutboundGatewaySpec
@@ -149,10 +152,26 @@ public class MongoDbOutboundGatewaySpec
* @param collectionCallback the {@link CollectionCallback} instance
* @param
the type of the message payload.
* @return the spec
+ * @deprecated in favor of {@link #collectionCallback(MessageCollectionCallback)}
*/
+ @Deprecated
public
MongoDbOutboundGatewaySpec collectionCallback(CollectionCallback
collectionCallback) {
this.target.setCollectionCallback(collectionCallback);
return this;
}
+ /**
+ * Reference to an instance of {@link MessageCollectionCallback}
+ * which specifies the database operation to execute in the request message context.
+ * This property is mutually exclusive with {@link #query} and {@link #queryExpression} properties.
+ * @param collectionCallback the {@link MessageCollectionCallback} instance
+ * @param
the type of the message payload.
+ * @return the spec
+ * @since 5.0.11
+ */
+ public
MongoDbOutboundGatewaySpec collectionCallback(MessageCollectionCallback
collectionCallback) {
+ this.target.setMessageCollectionCallback(collectionCallback);
+ return this;
+ }
+
}
diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MessageCollectionCallback.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MessageCollectionCallback.java
new file mode 100644
index 0000000000..f64d491f3f
--- /dev/null
+++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MessageCollectionCallback.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 the original author or authors.
+ *
+ * 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 org.springframework.integration.mongodb.outbound;
+
+import org.bson.Document;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.data.mongodb.core.CollectionCallback;
+import org.springframework.lang.Nullable;
+import org.springframework.messaging.Message;
+
+import com.mongodb.MongoException;
+import com.mongodb.client.MongoCollection;
+
+/**
+ * The callback to be used with the {@link MongoDbOutboundGateway}
+ * as an alternative to other query options on the gateway.
+ *
+ * Plays the same role as standard {@link CollectionCallback},
+ * but with {@code Message> requestMessage} context during {@code handleMessage()}
+ * process in the {@link MongoDbOutboundGateway}.
+ *
+ * @author Artem Bilan
+ *
+ * @since 5.0.11
+ *
+ * @see CollectionCallback
+ */
+@FunctionalInterface
+public interface MessageCollectionCallback extends CollectionCallback {
+
+ /**
+ * Perform a Mongo operation in the collection using request message as a context.
+ * @param collection never {@literal null}.
+ * @param requestMessage the request message ot use for operations
+ * @return can be {@literal null}.
+ * @throws MongoException the MongoDB-specific exception
+ * @throws DataAccessException the data access exception
+ */
+ @Nullable
+ T doInCollection(MongoCollection collection, Message> requestMessage)
+ throws MongoException, DataAccessException;
+
+ @Override
+ default T doInCollection(MongoCollection collection) throws MongoException, DataAccessException {
+ throw new UnsupportedOperationException("The 'doInCollection(MongoCollection, Message>)' " +
+ "must be implemented instead.");
+ }
+
+}
diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java
index 22b7e763a0..5d0a93e54f 100644
--- a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java
+++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGateway.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 the original author or authors.
+ * Copyright 2016-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,8 @@ import org.springframework.util.Assert;
* Makes outbound operations to query a MongoDb database using a {@link MongoOperations}
*
* @author Xavier Padró
+ * @author Artem Bilan
+ *
* @since 5.0
*/
public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler {
@@ -55,7 +57,7 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
private Expression queryExpression;
- private CollectionCallback> collectionCallback;
+ private MessageCollectionCallback> collectionCallback;
private boolean expectSingleResult = false;
@@ -90,8 +92,29 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
this.queryExpression = EXPRESSION_PARSER.parseExpression(queryExpressionString);
}
+ /**
+ * Specify a {@link CollectionCallback} to perform against MongoDB collection.
+ * @param collectionCallback the callback to perform against MongoDB collection.
+ * @deprecated in favor of {@link #setMessageCollectionCallback(MessageCollectionCallback)}.
+ * Will be removed in 5.2
+ */
+ @Deprecated
public void setCollectionCallback(CollectionCallback> collectionCallback) {
- Assert.notNull(collectionCallback, "collectionCallback must not be null.");
+ Assert.notNull(collectionCallback, "'collectionCallback' must not be null.");
+ this.collectionCallback =
+ collectionCallback instanceof MessageCollectionCallback
+ ? (MessageCollectionCallback) collectionCallback
+ : (collection, requestMessage) -> collectionCallback.doInCollection(collection);
+ }
+
+ /**
+ * Specify a {@link MessageCollectionCallback} to perform against MongoDB collection
+ * in the request message context.
+ * @param collectionCallback the callback to perform against MongoDB collection.
+ * @since 5.0.11
+ */
+ public void setMessageCollectionCallback(MessageCollectionCallback> collectionCallback) {
+ Assert.notNull(collectionCallback, "'collectionCallback' must not be null.");
this.collectionCallback = collectionCallback;
}
@@ -152,7 +175,8 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
Object result;
if (this.collectionCallback != null) {
- result = this.mongoTemplate.execute(collectionName, this.collectionCallback);
+ result = this.mongoTemplate.execute(collectionName, // NOSONAR
+ collection -> this.collectionCallback.doInCollection(collection, requestMessage));
}
else {
Query query = buildQuery(requestMessage);
diff --git a/spring-integration-mongodb/src/main/resources/org/springframework/integration/mongodb/config/spring-integration-mongodb-5.0.xsd b/spring-integration-mongodb/src/main/resources/org/springframework/integration/mongodb/config/spring-integration-mongodb-5.0.xsd
index 80e176ff22..6135884619 100644
--- a/spring-integration-mongodb/src/main/resources/org/springframework/integration/mongodb/config/spring-integration-mongodb-5.0.xsd
+++ b/spring-integration-mongodb/src/main/resources/org/springframework/integration/mongodb/config/spring-integration-mongodb-5.0.xsd
@@ -239,7 +239,10 @@
Reference to an instance of
- org.springframework.data.mongodb.core.CollectionCallback
+ org.springframework.data.mongodb.core.CollectionCallback, preferable an
+ instance of
+ org.springframework.integration.mongodb.outbound.MessageCollectionCallback
+ with the request message context.
f
- .handle(collectionCallbackOutboundGateway(MongoCollection::count))
+ .handle(collectionCallbackOutboundGateway(
+ (collection, requestMessage) -> collection.count()))
.channel(getResultChannel());
}
@@ -387,7 +390,9 @@ public class MongoDbTests extends MongoDbAvailableTests {
.entityClass(Person.class);
}
- private MongoDbOutboundGatewaySpec collectionCallbackOutboundGateway(CollectionCallback> collectionCallback) {
+ private MongoDbOutboundGatewaySpec collectionCallbackOutboundGateway(
+ MessageCollectionCallback> collectionCallback) {
+
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
.collectionCallback(collectionCallback)
.collectionName(COLLECTION_NAME)
diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGatewayTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGatewayTests.java
index 397b4d1cce..ef936b1b9a 100644
--- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGatewayTests.java
+++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/outbound/MongoDbOutboundGatewayTests.java
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;
@@ -49,17 +50,16 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import com.mongodb.client.MongoCollection;
+import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Xavier Padró
+ * @author Gary Rssell
+ * @author Artem Bilan
+ *
* @since 5.0
*/
-@ContextConfiguration
-@RunWith(SpringJUnit4ClassRunner.class)
+@RunWith(SpringRunner.class)
@DirtiesContext
public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@@ -95,14 +95,12 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
mongoTemplate.dropCollection(COLLECTION_NAME);
}
- @SuppressWarnings("ConstantConditions")
@Test
@MongoDbAvailable
public void testNoFactorySpecified() {
- MongoDbFactory nullFactory = null;
try {
- new MongoDbOutboundGateway(nullFactory);
+ new MongoDbOutboundGateway((MongoDbFactory) null);
Assert.fail("Expected the test case to throw an IllegalArgumentException");
}
catch (IllegalArgumentException e) {
@@ -110,14 +108,11 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
}
}
- @SuppressWarnings("ConstantConditions")
@Test
@MongoDbAvailable
public void testNoTemplateSpecified() {
- MongoOperations mongoTemplate = null;
-
try {
- new MongoDbOutboundGateway(mongoTemplate);
+ new MongoDbOutboundGateway((MongoTemplate) null);
Assert.fail("Expected the test case to throw an IllegalArgumentException");
}
catch (IllegalArgumentException e) {
@@ -193,7 +188,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testListOfResultsWithQueryExpression() throws Exception {
+ public void testListOfResultsWithQueryExpression() {
Message message = MessageBuilder.withPayload("{}").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setEntityClass(Person.class);
@@ -208,7 +203,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testListOfResultsWithQueryExpressionReturningOneResult() throws Exception {
+ public void testListOfResultsWithQueryExpressionReturningOneResult() {
Message message = MessageBuilder.withPayload("{name : 'Xavi'}").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setEntityClass(Person.class);
@@ -224,7 +219,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testSingleResultWithQueryExpressionAsString() throws Exception {
+ public void testSingleResultWithQueryExpressionAsString() {
Message message = MessageBuilder.withPayload("{name : 'Artem'}").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setQueryExpression(PARSER.parseExpression("payload"));
@@ -240,7 +235,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testSingleResultWithQueryExpressionAsQuery() throws Exception {
+ public void testSingleResultWithQueryExpressionAsQuery() {
Message message = MessageBuilder.withPayload("").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setQueryExpression(PARSER.parseExpression("new BasicQuery('{''name'' : ''Gary''}')"));
@@ -271,7 +266,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testWithNullCollectionNameExpression() throws Exception {
+ public void testWithNullCollectionNameExpression() {
MongoDbOutboundGateway gateway = new MongoDbOutboundGateway(mongoDbFactory);
gateway.setBeanFactory(beanFactory);
gateway.setQueryExpression(new LiteralExpression("{name : 'Xavi'}"));
@@ -288,7 +283,7 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testWithCollectionNameExpressionSpecified() throws Exception {
+ public void testWithCollectionNameExpressionSpecified() {
Message message = MessageBuilder.withPayload("").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setQueryExpression(new LiteralExpression("{name : 'Xavi'}"));
@@ -307,13 +302,13 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testWithCollectionCallbackCount() throws Exception {
+ public void testWithCollectionCallbackCount() {
Message message = MessageBuilder.withPayload("").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setEntityClass(Person.class);
gateway.setCollectionNameExpression(new LiteralExpression("data"));
- gateway.setCollectionCallback(MongoCollection::count);
+ gateway.setMessageCollectionCallback((collection, requestMessage) -> collection.count());
gateway.afterPropertiesSet();
long result = (long) gateway.handleRequestMessage(message);
@@ -323,15 +318,15 @@ public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
@Test
@MongoDbAvailable
- public void testWithCollectionCallbackFindOne() throws Exception {
- Message message = MessageBuilder.withPayload("").build();
+ public void testWithCollectionCallbackFindOne() {
+ Message message = MessageBuilder.withPayload("Mike").build();
MongoDbOutboundGateway gateway = createGateway();
gateway.setEntityClass(Person.class);
gateway.setCollectionNameExpression(new LiteralExpression("data"));
gateway.setRequiresReply(false);
- gateway.setCollectionCallback(collection -> {
- collection.insertOne(new Document("name", "Mike"));
+ gateway.setMessageCollectionCallback((collection, requestMessage) -> {
+ collection.insertOne(new Document("name", requestMessage.getPayload()));
return null;
});
gateway.afterPropertiesSet();
diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/rules/MongoDbAvailableTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/rules/MongoDbAvailableTests.java
index f8aa7a2727..4700f856c0 100644
--- a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/rules/MongoDbAvailableTests.java
+++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/rules/MongoDbAvailableTests.java
@@ -23,13 +23,14 @@ import org.junit.Rule;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.MongoDbFactory;
-import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
+import org.springframework.integration.mongodb.outbound.MessageCollectionCallback;
+import org.springframework.messaging.Message;
import com.mongodb.MongoClient;
import com.mongodb.MongoException;
@@ -64,7 +65,7 @@ public abstract class MongoDbAvailableTests {
}
}
- public Person createPerson() {
+ protected Person createPerson() {
Address address = new Address();
address.setCity("Philadelphia");
address.setStreet("2121 Rawn street");
@@ -76,7 +77,7 @@ public abstract class MongoDbAvailableTests {
return person;
}
- public Person createPerson(String name) {
+ protected Person createPerson(String name) {
Address address = new Address();
address.setCity("Philadelphia");
address.setStreet("2121 Rawn street");
@@ -166,10 +167,12 @@ public abstract class MongoDbAvailableTests {
}
- public static class TestCollectionCallback implements CollectionCallback {
+ public static class TestCollectionCallback implements MessageCollectionCallback {
@Override
- public Long doInCollection(MongoCollection collection) throws MongoException, DataAccessException {
+ public Long doInCollection(MongoCollection collection, Message> message)
+ throws MongoException, DataAccessException {
+
return collection.count();
}
diff --git a/src/reference/asciidoc/mongodb.adoc b/src/reference/asciidoc/mongodb.adoc
index b4ca7a0cdb..3ef7e371a1 100644
--- a/src/reference/asciidoc/mongodb.adoc
+++ b/src/reference/asciidoc/mongodb.adoc
@@ -187,12 +187,14 @@ The _MongoDb Inbound Channel Adapter_ is a polling consumer that reads data from
As you can see from the configuration above, you configure a _MongoDb Inbound Channel Adapter_ using the `inbound-channel-adapter` element, providing values for various attributes such as:
-* `query` - a JSON query (see http://www.mongodb.org/display/DOCS/Querying[MongoDb Querying])
-* `query-expression` - A SpEL expression that is evaluated to a JSON query String (as the `query` attribute above), or to an instance of `o.s.data.mongodb.core.query.Query`. Mutually exclusive with `query` attribute.
-* `entity-class` - the type of the payload object; if not supplied, a `com.mongodb.DBObject` will be returned.
-* `collection-name` or `collection-name-expression` - Identifies the name of the MongoDb collection to use.
-* `mongodb-factory` - reference to an instance of `o.s.data.mongodb.MongoDbFactory`
-* `mongo-template` - reference to an instance of `o.s.data.mongodb.core.MongoTemplate`
+* `query`: A JSON query (see http://www.mongodb.org/display/DOCS/Querying[MongoDB Querying])
+* `query-expression`: A SpEL expression that is evaluated to a JSON query string (as the `query` attribute above) or to an instance of `o.s.data.mongodb.core.query.Query`.
+Mutually exclusive with the `query` attribute.
+* `entity-class`: The type of the payload object. If not supplied, a `com.mongodb.DBObject` is returned.
+* `collection-name` or `collection-name-expression`: Identifies the name of the MongoDB collection to use.
+* `mongodb-factory`: Reference to an instance of `o.s.data.mongodb.MongoDbFactory`
+* `mongo-template`: Reference to an instance of `o.s.data.mongodb.core.MongoTemplate`
+* Other attributes that are common across all other inbound adapters (such as 'channel').
@@ -321,6 +323,20 @@ Please refer to http://www.mongodb.org/display/DOCS/Querying[MongoDB documentati
* `collection-callback` - reference to an instance of `org.springframework.data.mongodb.core.CollectionCallback`
(NOTE: you can not have both collection-callback and any of the query attributes).
+* `collection-name` or `collection-name-expression`: Identifies the name of the MongoDB collection to use.
+* `mongo-converter`: Reference to an instance of `o.s.data.mongodb.core.convert.MongoConverter` that assists with converting a raw Java object to a JSON document representation.
+* `mongodb-factory`: Reference to an instance of `o.s.data.mongodb.MongoDbFactory`.
+* `mongo-template`: Reference to an instance of `o.s.data.mongodb.core.MongoTemplate`.
+NOTE: you can not set both `mongo-template` and `mongodb-factory`.
+* `entity-class`: The fully qualified name of the entity class to be passed to the `find(..)` and `findOne(..)` methods in MongoTemplate.
+If this attribute is not provided, the default value is `org.bson.Document`.
+* `query` or `query-expression`: Specifies the MongoDB query.
+See the http://www.mongodb.org/display/DOCS/Querying[MongoDB documentation] for more query samples.
+* `collection-callback`: Reference to an instance of `org.springframework.data.mongodb.core.CollectionCallback`.
+Preferable an instance of `org.springframework.integration.mongodb.outbound.MessageCollectionCallback` since 5.0.11 with the request message context.
+See its Javadocs for more information.
+NOTE: You can not have both `collection-callback` and any of the query attributes.
+
==== Configuring with Java Configuration
The following Spring Boot application provides an example of configuring the outbound gateway using Java configuration:
@@ -399,15 +415,14 @@ public class MongoDbJavaApplication {
}
----
-Alternatively to the `query` and `query-expression` properties, you can specify other database operations through
-the `collectionCallback` property.
+As an alternate to the `query` and `query-expression` properties, you can specify other database operations by using the `collectionCallback` property as a reference to the `MessageCollectionCallback` functional interface implementation.
The following example specifies a count operation:
[source, java]
----
private MongoDbOutboundGatewaySpec collectionCallbackOutboundGateway() {
return MongoDb.outboundGateway(this.mongoDbFactory, this.mongoConverter)
- .collectionCallback(MongoCollection::count)
+ .collectionCallback((collection, requestMessage) -> collection.count())
.collectionName("foo");
}
----