INT-4196: MongoOutGateway: add CollectionCallback

JIRA: https://jira.spring.io/browse/INT-4196

Add `CollectionCallback` option to the `MongoDbOutboundGateway`

Add XML support to CollectionCallback

Fix PR comments

Fix issue with javadoc parsing

* Polishing code style, JavaDocs and some Docs
This commit is contained in:
Xavier Padro
2016-12-27 12:41:54 +01:00
committed by Artem Bilan
parent d973295631
commit 739ebb744b
15 changed files with 364 additions and 41 deletions

View File

@@ -42,18 +42,28 @@ public class MongoDbOutboundGatewayParser extends AbstractConsumerEndpointParser
MongoParserUtils.processCommonAttributes(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout");
String replyChannel = element.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
builder.addPropertyReference("outputChannel", replyChannel);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
String collectionCallback = element.getAttribute("collection-callback");
if (StringUtils.hasText(collectionCallback)) {
if (StringUtils.hasText(element.getAttribute("query")) ||
StringUtils.hasText(element.getAttribute("query-expression"))) {
parserContext.getReaderContext().error("'collection-callback' is not allowed with " +
"'query' or 'query-expression'", element);
}
builder.addPropertyReference("collectionCallback", collectionCallback);
}
else {
BeanDefinition queryExpressionDef =
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("query",
"query-expression", parserContext, element, true);
BeanDefinition queryExpressionDef =
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("query",
"query-expression", parserContext, element, true);
if (queryExpressionDef != null) {
builder.addPropertyValue("queryExpression", queryExpressionDef);
if (queryExpressionDef != null) {
builder.addPropertyValue("queryExpression", queryExpressionDef);
}
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expect-single-result");

View File

@@ -28,12 +28,25 @@ import org.springframework.data.mongodb.core.convert.MongoConverter;
*/
public final class MongoDb {
/**
* Create a {@link MongoDbOutboundGatewaySpec} builder instance
* based on the provided {@link MongoDbFactory} and {@link MongoConverter}.
* @param mongoDbFactory the {@link MongoDbFactory} to use.
* @param mongoConverter the {@link MongoConverter} to use.
* @return the {@link MongoDbOutboundGatewaySpec} instance
*/
public static MongoDbOutboundGatewaySpec outboundGateway(
MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
return new MongoDbOutboundGatewaySpec(mongoDbFactory, mongoConverter);
}
/**
* Create a {@link MongoDbOutboundGatewaySpec} builder instance
* based on the provided {@link MongoOperations}.
* @param mongoTemplate the {@link MongoOperations} to use.
* @return the {@link MongoDbOutboundGatewaySpec} instance
*/
public static MongoDbOutboundGatewaySpec outboundGateway(MongoOperations mongoTemplate) {
return new MongoDbOutboundGatewaySpec(mongoTemplate);
}

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.mongodb.dsl;
import java.util.function.Function;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Query;
@@ -47,44 +48,111 @@ public class MongoDbOutboundGatewaySpec
this.target.setRequiresReply(true);
}
/**
* This parameter indicates that only one result object will be returned from the database
* by using a {@code findOne} query.
* If set to {@code false} (default), the complete result list is returned as the payload.
* @param expectSingleResult the {@code boolean} flag to indicate if a single result is returned or not.
* @return the spec
*/
public MongoDbOutboundGatewaySpec expectSingleResult(boolean expectSingleResult) {
this.target.setExpectSingleResult(expectSingleResult);
return this;
}
/**
* A {@code String} representation of a MongoDb {@link Query} (e.g., query("{'name' : 'Bob'}")).
* Please refer to MongoDb documentation for more query samples
* see <a href="http://www.mongodb.org/display/DOCS/Querying">MongoDB Docs</a>
* This property is mutually exclusive with 'queryExpression' property.
* @param query the MongoDb {@link Query} string representation to use.
* @return the spec
*/
public MongoDbOutboundGatewaySpec query(String query) {
this.target.setQueryExpression(new LiteralExpression(query));
return this;
}
/**
* A SpEL expression which should resolve to a {@code String} query (please refer to the 'query' property),
* or to an instance of MongoDb {@link Query}
* (e.q., queryExpression("new BasicQuery('{''address.state'' : ''PA''}')")).
* @param queryExpression the SpEL expression query to use.
* @return the spec
*/
public MongoDbOutboundGatewaySpec queryExpression(String queryExpression) {
this.target.setQueryExpressionString(queryExpression);
return this;
}
/**
* A {@link Function} which should resolve to a {@link Query} instance.
* @param queryFunction the {@link Function} to use.
* @param <P> the type of the message payload.
* @return the spec
*/
public <P> MongoDbOutboundGatewaySpec queryFunction(Function<Message<P>, Query> queryFunction) {
this.target.setQueryExpression(new FunctionExpression<>(queryFunction));
return this;
}
/**
* The fully qualified name of the entity class to be passed
* to {@code find(..)} or {@code findOne(..)} method in {@link MongoOperations}.
* If this attribute is not provided the default value is {@link org.bson.Document}.
* @param entityClass the {@link Class} to use.
* @return the spec
*/
public MongoDbOutboundGatewaySpec entityClass(Class<?> entityClass) {
this.target.setEntityClass(entityClass);
return this;
}
/**
* Identify the name of the MongoDb collection to use.
* This attribute is mutually exclusive with {@link #collectionNameExpression} property.
* @param collectionName the {@link String} specifying the MongoDb collection.
* @return the spec
*/
public MongoDbOutboundGatewaySpec collectionName(String collectionName) {
this.target.setCollectionNameExpression(new LiteralExpression(collectionName));
return this;
}
/**
* A SpEL expression which should resolve to a {@link String} value
* identifying the name of the MongoDb collection to use.
* This property is mutually exclusive with {@link #collectionName} property.
* @param collectionNameExpression the {@link String} expression to use.
* @return the spec
*/
public MongoDbOutboundGatewaySpec collectionNameExpression(String collectionNameExpression) {
this.target.setCollectionNameExpressionString(collectionNameExpression);
return this;
}
/**
* A {@link Function} which should resolve to a {@link String}
* (e.q., {@code collectionNameFunction(Message::getPayload)}).
* @param collectionNameFunction the {@link Function} to use.
* @param <P> the type of the message payload.
* @return the spec
*/
public <P> MongoDbOutboundGatewaySpec collectionNameFunction(Function<Message<P>, String> collectionNameFunction) {
this.target.setCollectionNameExpression(new FunctionExpression<>(collectionNameFunction));
return this;
}
/**
* Reference to an instance of {@link CollectionCallback} which specifies the database operation to execute.
* This property is mutually exclusive with {@link #query} and {@link #queryExpression} properties.
* @param collectionCallback the {@link CollectionCallback} instance
* @param <P> the type of the message payload.
* @return the spec
*/
public <P> MongoDbOutboundGatewaySpec collectionCallback(CollectionCallback<P> collectionCallback) {
this.target.setCollectionCallback(collectionCallback);
return this;
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.mongodb.outbound;
import org.bson.Document;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
@@ -54,6 +55,8 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
private Expression queryExpression;
private CollectionCallback<?> collectionCallback;
private boolean expectSingleResult = false;
private Class<?> entityClass = Document.class;
@@ -87,6 +90,11 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
this.queryExpression = EXPRESSION_PARSER.parseExpression(queryExpressionString);
}
public void setCollectionCallback(CollectionCallback<?> collectionCallback) {
Assert.notNull(collectionCallback, "collectionCallback must not be null.");
this.collectionCallback = collectionCallback;
}
public void setExpectSingleResult(boolean expectSingleResult) {
this.expectSingleResult = expectSingleResult;
}
@@ -115,8 +123,12 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
@Override
protected void doInit() {
Assert.state(this.queryExpression != null, "no query specified");
Assert.state(this.queryExpression != null || this.collectionCallback != null,
"no query or collectionCallback is specified");
Assert.state(this.collectionNameExpression != null, "no collection name specified");
if (this.queryExpression != null && this.collectionCallback != null) {
throw new IllegalStateException("query and collectionCallback are mutually exclusive");
}
if (this.evaluationContext == null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
@@ -136,15 +148,21 @@ public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler
protected Object handleRequestMessage(Message<?> requestMessage) {
String collectionName =
this.collectionNameExpression.getValue(this.evaluationContext, requestMessage, String.class);
Query query = buildQuery(requestMessage);
Object result;
if (this.expectSingleResult) {
result = this.mongoTemplate.findOne(query, this.entityClass, collectionName);
if (this.collectionCallback != null) {
result = this.mongoTemplate.execute(collectionName, this.collectionCallback);
}
else {
result = this.mongoTemplate.find(query, this.entityClass, collectionName);
Query query = buildQuery(requestMessage);
if (this.expectSingleResult) {
result = this.mongoTemplate.findOne(query, this.entityClass, collectionName);
}
else {
result = this.mongoTemplate.find(query, this.entityClass, collectionName);
}
}
return result;

View File

@@ -234,6 +234,20 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="collection-callback" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to an instance of
org.springframework.data.mongodb.core.CollectionCallback
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.data.mongodb.core.CollectionCallback" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>