INT-3335: Implement MongoDb Outbound Gateway
JIRA: https://jira.spring.io/browse/INT-3335 INT-3335: PR fixes INT-3335: fix code style INT-3335: Add queryExpressionString + minor fixes * Polishing. Mostly code style
This commit is contained in:
committed by
Artem Bilan
parent
318bb4c4b7
commit
0fa8849f7f
@@ -31,5 +31,6 @@ public class MongoDbNamespaceHandler extends AbstractIntegrationNamespaceHandler
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new MongoDbInboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new MongoDbOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-gateway", new MongoDbOutboundGatewayParser());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2016 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.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.mongodb.outbound.MongoDbOutboundGateway;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for MongoDb outbound gateways
|
||||
*
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MongoDbOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
final BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(MongoDbOutboundGateway.class);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
BeanDefinition queryExpressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("query",
|
||||
"query-expression", parserContext, element, true);
|
||||
|
||||
if (queryExpressionDef != null) {
|
||||
builder.addPropertyValue("queryExpression", queryExpressionDef);
|
||||
}
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expect-single-result");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "entity-class");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInputChannelAttributeName() {
|
||||
return "request-channel";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 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.dsl;
|
||||
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
|
||||
/**
|
||||
* Factory class for building MongoDb components
|
||||
*
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
public final class MongoDb {
|
||||
|
||||
public static MongoDbOutboundGatewaySpec outboundGateway(
|
||||
MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
|
||||
|
||||
return new MongoDbOutboundGatewaySpec(mongoDbFactory, mongoConverter);
|
||||
}
|
||||
|
||||
public static MongoDbOutboundGatewaySpec outboundGateway(MongoOperations mongoTemplate) {
|
||||
return new MongoDbOutboundGatewaySpec(mongoTemplate);
|
||||
}
|
||||
|
||||
private MongoDb() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2016 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.dsl;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
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.MongoDbOutboundGateway;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* A {@link MessageHandlerSpec} extension for the MongoDb Outbound endpoint {@link MongoDbOutboundGateway}
|
||||
*
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MongoDbOutboundGatewaySpec
|
||||
extends MessageHandlerSpec<MongoDbOutboundGatewaySpec, MongoDbOutboundGateway> {
|
||||
|
||||
MongoDbOutboundGatewaySpec(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
|
||||
this.target = new MongoDbOutboundGateway(mongoDbFactory, mongoConverter);
|
||||
this.target.setRequiresReply(true);
|
||||
}
|
||||
|
||||
MongoDbOutboundGatewaySpec(MongoOperations mongoTemplate) {
|
||||
this.target = new MongoDbOutboundGateway(mongoTemplate);
|
||||
this.target.setRequiresReply(true);
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec expectSingleResult(boolean expectSingleResult) {
|
||||
this.target.setExpectSingleResult(expectSingleResult);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec query(String query) {
|
||||
this.target.setQueryExpression(new LiteralExpression(query));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec queryExpression(String queryExpression) {
|
||||
this.target.setQueryExpressionString(queryExpression);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <P> MongoDbOutboundGatewaySpec queryFunction(Function<Message<P>, Query> queryFunction) {
|
||||
this.target.setQueryExpression(new FunctionExpression<>(queryFunction));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec entityClass(Class<?> entityClass) {
|
||||
this.target.setEntityClass(entityClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec collectionName(String collectionName) {
|
||||
this.target.setCollectionNameExpression(new LiteralExpression(collectionName));
|
||||
return this;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGatewaySpec collectionNameExpression(String collectionNameExpression) {
|
||||
this.target.setCollectionNameExpressionString(collectionNameExpression);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <P> MongoDbOutboundGatewaySpec collectionNameFunction(Function<Message<P>, String> collectionNameFunction) {
|
||||
this.target.setCollectionNameExpression(new FunctionExpression<>(collectionNameFunction));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides MongoDB Components support for Java DSL.
|
||||
*/
|
||||
package org.springframework.integration.mongodb.dsl;
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2016 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.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Makes outbound operations to query a MongoDb database using a {@link MongoOperations}
|
||||
*
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MongoDbOutboundGateway extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
private MongoDbFactory mongoDbFactory;
|
||||
|
||||
private MongoConverter mongoConverter;
|
||||
|
||||
private MongoOperations mongoTemplate;
|
||||
|
||||
private EvaluationContext evaluationContext;
|
||||
|
||||
private Expression queryExpression;
|
||||
|
||||
private boolean expectSingleResult = false;
|
||||
|
||||
private Class<?> entityClass = Document.class;
|
||||
|
||||
private Expression collectionNameExpression;
|
||||
|
||||
public MongoDbOutboundGateway(MongoDbFactory mongoDbFactory) {
|
||||
this(mongoDbFactory, new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory),
|
||||
new MongoMappingContext()));
|
||||
}
|
||||
|
||||
public MongoDbOutboundGateway(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
|
||||
Assert.notNull(mongoDbFactory, "mongoDbFactory must not be null.");
|
||||
Assert.notNull(mongoConverter, "mongoConverter must not be null.");
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.mongoConverter = mongoConverter;
|
||||
}
|
||||
|
||||
public MongoDbOutboundGateway(MongoOperations mongoTemplate) {
|
||||
Assert.notNull(mongoTemplate, "mongoTemplate must not be null.");
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
public void setQueryExpression(Expression queryExpression) {
|
||||
Assert.notNull(queryExpression, "queryExpression must not be null.");
|
||||
this.queryExpression = queryExpression;
|
||||
}
|
||||
|
||||
public void setQueryExpressionString(String queryExpressionString) {
|
||||
Assert.notNull(queryExpressionString, "queryExpressionString must not be null.");
|
||||
this.queryExpression = EXPRESSION_PARSER.parseExpression(queryExpressionString);
|
||||
}
|
||||
|
||||
public void setExpectSingleResult(boolean expectSingleResult) {
|
||||
this.expectSingleResult = expectSingleResult;
|
||||
}
|
||||
|
||||
public void setEntityClass(Class<?> entityClass) {
|
||||
Assert.notNull(entityClass, "entityClass must not be null.");
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
public void setCollectionNameExpression(Expression collectionNameExpression) {
|
||||
Assert.notNull(collectionNameExpression, "collectionNameExpression must not be null.");
|
||||
this.collectionNameExpression = collectionNameExpression;
|
||||
}
|
||||
|
||||
public void setCollectionNameExpressionString(String collectionNameExpressionString) {
|
||||
Assert.notNull(collectionNameExpressionString, "collectionNameExpressionString must not be null.");
|
||||
this.collectionNameExpression = EXPRESSION_PARSER.parseExpression(collectionNameExpressionString);
|
||||
}
|
||||
|
||||
public void setMongoConverter(MongoConverter mongoConverter) {
|
||||
Assert.notNull(mongoConverter, "mongoConverter cannot be null");
|
||||
Assert.isNull(this.mongoTemplate,
|
||||
"'mongoConverter' can not be set when instance was constructed with MongoTemplate");
|
||||
this.mongoConverter = mongoConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
Assert.state(this.queryExpression != null, "no query specified");
|
||||
Assert.state(this.collectionNameExpression != null, "no collection name specified");
|
||||
|
||||
if (this.evaluationContext == null) {
|
||||
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
|
||||
|
||||
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
|
||||
if (typeLocator instanceof StandardTypeLocator) {
|
||||
((StandardTypeLocator) typeLocator).registerImport(Query.class.getPackage().getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mongoTemplate == null) {
|
||||
this.mongoTemplate = new MongoTemplate(this.mongoDbFactory, this.mongoConverter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
else {
|
||||
result = this.mongoTemplate.find(query, this.entityClass, collectionName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Query buildQuery(Message<?> requestMessage) {
|
||||
Query query;
|
||||
|
||||
Object expressionValue =
|
||||
this.queryExpression.getValue(this.evaluationContext, requestMessage, Object.class);
|
||||
|
||||
if (expressionValue instanceof String) {
|
||||
query = new BasicQuery((String) expressionValue);
|
||||
}
|
||||
else if (expressionValue instanceof Query) {
|
||||
query = ((Query) expressionValue);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("'queryExpression' must evaluate to " +
|
||||
"String or org.springframework.data.mongodb.core.query.Query");
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -102,6 +102,143 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configures a Consumer Endpoint for the
|
||||
'org.springframework.integration.mongodb.outbound.MongoDbOutboundGateway' for
|
||||
querying a MongoDb database in response to a message on the request channel.
|
||||
|
||||
The response received from the database will be used to create the response
|
||||
Message on the reply channel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="mongodbAdapterType">
|
||||
<xsd:attribute name="request-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The Message Channel where messages will be sent in order
|
||||
to query the database.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.messaging.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The Message Channel to which the database response will be sent.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.messaging.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Allows you to specify how long this gateway will wait for
|
||||
the reply message to be sent successfully to the reply channel
|
||||
before throwing an exception. This attribute only applies when the
|
||||
channel might block, for example when using a bounded queue channel that
|
||||
is currently full.
|
||||
|
||||
Also, keep in mind that when sending to a DirectChannel, the
|
||||
invocation will occur in the sender's thread. Therefore,
|
||||
the failing of the send operation may be caused by other
|
||||
components further downstream.
|
||||
|
||||
The "reply-timeout" attribute maps to the "sendTimeout" property of the
|
||||
underlying 'MessagingTemplate' instance (org.springframework.integration.core.MessagingTemplate).
|
||||
|
||||
The attribute will default, if not specified, to '-1', meaning that
|
||||
by default, the Gateway will wait indefinitely. The value is
|
||||
specified in milliseconds.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="requires-reply" use="optional" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether this outbound gateway must return a non-null value. This value is
|
||||
'true' by default, and a ReplyRequiredException will be thrown when
|
||||
the underlying service returns a null value.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies the order for invocation when this endpoint is connected as a
|
||||
subscriber to a SubscribableChannel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expect-single-result">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This parameter indicates that only one result object will be
|
||||
returned from the database by using a findOne query.
|
||||
|
||||
If set to 'false', the complete result list is returned
|
||||
as the payload.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="query" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
String representation of a MongoDb Query (e.g.,
|
||||
query="{'name' : 'Bob'}").
|
||||
Please refer to MongoDb documentation for more query samples
|
||||
http://www.mongodb.org/display/DOCS/Querying
|
||||
This attribute is
|
||||
mutually exclusive with 'query-expression' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="query-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression which should resolve to a String query (please refer to the 'query'
|
||||
attribute), or to an instance of MongoDb Query (e.q.,
|
||||
query-expression="new BasicQuery('{''name'' : ''Bob''}').limit(2)").
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="entity-class" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The fully qualified name of the entity class to be passed to
|
||||
find(..) or findOne(..) method MongoTemplate.
|
||||
If this attribute is not provided the default value is org.bson.Document
|
||||
</xsd:documentation>
|
||||
<tool:annotation kind="direct">
|
||||
<tool:expected-type type="java.lang.Class" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="mongodbAdapterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb.xsd">
|
||||
|
||||
<int:channel id="in"/>
|
||||
<int:channel id="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="minimalConfig"
|
||||
query="{'name' : 'foo'}"
|
||||
collection-name="foo"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="fullConfigWithCollectionExpression"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
collection-name-expression="headers.collectionName"
|
||||
query="{'name' : 'foo'}"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="fullConfigWithCollection"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query="{'name' : 'foo'}"
|
||||
collection-name="foo"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="fullConfigWithTemplate"
|
||||
mongo-template="mongoDbTemplate"
|
||||
collection-name="foo"
|
||||
query="{'name' : 'foo'}"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<bean id="mongoDbFactory" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.data.mongodb.MongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoConverter" class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.TestMongoConverter">
|
||||
<constructor-arg ref="mongoDbFactory"/>
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.mongodb.core.mapping.MongoMappingContext"/>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoDbTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="mongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2016 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.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.integration.mongodb.outbound.MongoDbOutboundGateway;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbOutboundGatewayParserTests {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MongoDbFactory mongoDbFactory;
|
||||
|
||||
@Autowired
|
||||
private MongoConverter mongoConverter;
|
||||
|
||||
@Test
|
||||
public void minimalConfig() {
|
||||
MongoDbOutboundGateway gateway =
|
||||
TestUtils.getPropertyValue(context.getBean("minimalConfig"), "handler", MongoDbOutboundGateway.class);
|
||||
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "mongoTemplate"));
|
||||
assertSame(this.mongoDbFactory, TestUtils.getPropertyValue(gateway, "mongoDbFactory"));
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(gateway, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(gateway, "collectionNameExpression.literalValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithCollectionExpression() {
|
||||
MongoDbOutboundGateway gateway = TestUtils.getPropertyValue(
|
||||
context.getBean("fullConfigWithCollectionExpression"), "handler", MongoDbOutboundGateway.class);
|
||||
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "mongoTemplate"));
|
||||
assertSame(this.mongoDbFactory, TestUtils.getPropertyValue(gateway, "mongoDbFactory"));
|
||||
assertSame(this.mongoConverter, TestUtils.getPropertyValue(gateway, "mongoConverter"));
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(gateway, "collectionNameExpression") instanceof SpelExpression);
|
||||
assertEquals("headers.collectionName",
|
||||
TestUtils.getPropertyValue(gateway, "collectionNameExpression.expression"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithCollection() {
|
||||
MongoDbOutboundGateway gateway = TestUtils.getPropertyValue(
|
||||
context.getBean("fullConfigWithCollection"), "handler", MongoDbOutboundGateway.class);
|
||||
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "mongoTemplate"));
|
||||
assertSame(this.mongoDbFactory, TestUtils.getPropertyValue(gateway, "mongoDbFactory"));
|
||||
assertSame(this.mongoConverter, TestUtils.getPropertyValue(gateway, "mongoConverter"));
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(gateway, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(gateway, "collectionNameExpression.literalValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithMongoTemplate() {
|
||||
MongoDbOutboundGateway gateway = TestUtils.getPropertyValue(
|
||||
context.getBean("fullConfigWithTemplate"), "handler", MongoDbOutboundGateway.class);
|
||||
|
||||
assertEquals(context.getBean("mongoDbTemplate"), TestUtils.getPropertyValue(gateway, "mongoTemplate"));
|
||||
assertNull(TestUtils.getPropertyValue(gateway, "mongoDbFactory"));
|
||||
assertNull(TestUtils.getPropertyValue(gateway, "mongoConverter"));
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(gateway, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(gateway, "collectionNameExpression.literalValue"));
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void templateAndFactoryFail() {
|
||||
new ClassPathXmlApplicationContext("outbound-gateway-fail-template-factory-config.xml", this.getClass())
|
||||
.close();
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void templateAndConverterFail() {
|
||||
new ClassPathXmlApplicationContext("outbound-gateway-fail-template-converter-config.xml",
|
||||
this.getClass()).close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb.xsd">
|
||||
|
||||
|
||||
<int:channel id="in"/>
|
||||
<int:channel id="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewayWithConverterAndTemplate"
|
||||
mongo-converter="mongoConverter"
|
||||
mongo-template="mongoDbTemplate"
|
||||
collection-name="foo"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<bean id="mongoDbFactory" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.data.mongodb.MongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoDbTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="mongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoConverter" class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.TestMongoConverter">
|
||||
<constructor-arg ref="mongoDbFactory"/>
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.mongodb.core.mapping.MongoMappingContext"/>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb.xsd">
|
||||
|
||||
|
||||
<int:channel id="in"/>
|
||||
<int:channel id="out"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewayWithFactoryAndTemplate"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-template="mongoDbTemplate"
|
||||
collection-name="foo"
|
||||
request-channel="in"
|
||||
reply-channel="out"/>
|
||||
|
||||
<bean id="mongoDbFactory" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.data.mongodb.MongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoDbTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="mongoDbFactory"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright 2016 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.dsl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.SimpleMongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
import org.springframework.integration.dsl.channel.MessageChannels;
|
||||
import org.springframework.integration.handler.ReplyRequiredException;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailableTests;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
/**
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbTests extends MongoDbAvailableTests {
|
||||
|
||||
private static final String COLLECTION_NAME = "data";
|
||||
|
||||
@Autowired
|
||||
private PollableChannel getResultChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewaySingleQueryFlow.input")
|
||||
private MessageChannel gatewaySingleQueryFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewaySingleQueryWithTemplateFlow.input")
|
||||
private MessageChannel gatewaySingleQueryWithTemplateFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewaySingleQueryExpressionFlow.input")
|
||||
private MessageChannel gatewaySingleQueryExpressionFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayQueryExpressionFlow.input")
|
||||
private MessageChannel gatewayQueryExpressionFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayQueryExpressionLimitFlow.input")
|
||||
private MessageChannel gatewayQueryExpressionLimitFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayQueryFunctionFlow.input")
|
||||
private MessageChannel gatewayQueryFunctionFlow;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayCollectionNameFunctionFlow.input")
|
||||
private MessageChannel gatewayCollectionNameFunctionFlow;
|
||||
|
||||
@Autowired
|
||||
private MongoOperations mongoTemplate;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
createPersons();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mongoTemplate.dropCollection(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithSingleQuery() {
|
||||
gatewaySingleQueryFlow.send(MessageBuilder
|
||||
.withPayload("Xavi")
|
||||
.setHeader("collection", "data")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
Person retrievedPerson = (Person) result.getPayload();
|
||||
assertEquals("Xavi", retrievedPerson.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithSingleQueryWithTemplate() {
|
||||
gatewaySingleQueryWithTemplateFlow.send(MessageBuilder.withPayload("Xavi").build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
Person retrievedPerson = (Person) result.getPayload();
|
||||
assertEquals("Xavi", retrievedPerson.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithSingleQueryExpression() {
|
||||
gatewaySingleQueryExpressionFlow.send(MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{'name' : 'Artem'}")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
Person retrievedPerson = (Person) result.getPayload();
|
||||
assertEquals("Artem", retrievedPerson.getName());
|
||||
}
|
||||
|
||||
@Test(expected = ReplyRequiredException.class)
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithSingleQueryExpressionNoPersonFound() {
|
||||
gatewaySingleQueryExpressionFlow.send(MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{'name' : 'NonExisting'}")
|
||||
.build());
|
||||
|
||||
this.getResultChannel.receive(10_000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithQueryExpression() {
|
||||
gatewayQueryExpressionFlow.send(MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{}")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
List<Person> retrievedPersons = getPersons(result);
|
||||
assertEquals(4, retrievedPersons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithQueryExpressionAndLimit() {
|
||||
gatewayQueryExpressionLimitFlow.send(MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{}")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
List<Person> retrievedPersons = getPersons(result);
|
||||
assertEquals(2, retrievedPersons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithQueryFunction() {
|
||||
gatewayQueryFunctionFlow.send(MessageBuilder
|
||||
.withPayload("Gary")
|
||||
.setHeader("collection", "data")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
Person person = (Person) result.getPayload();
|
||||
assertEquals("Gary", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testGatewayWithCollectionNameFunction() {
|
||||
gatewayCollectionNameFunctionFlow.send(MessageBuilder
|
||||
.withPayload("data")
|
||||
.setHeader("query", "{'name' : 'Gary'}")
|
||||
.build());
|
||||
|
||||
Message<?> result = this.getResultChannel.receive(10_000);
|
||||
|
||||
assertNotNull(result);
|
||||
Person person = (Person) result.getPayload();
|
||||
assertEquals("Gary", person.getName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Person> getPersons(Message<?> message) {
|
||||
return (List<Person>) message.getPayload();
|
||||
}
|
||||
|
||||
private void createPersons() {
|
||||
BulkOperations bulkOperations = this.mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, COLLECTION_NAME);
|
||||
bulkOperations.insert(Arrays.asList(
|
||||
this.createPerson("Artem"),
|
||||
this.createPerson("Gary"),
|
||||
this.createPerson("Oleg"),
|
||||
this.createPerson("Xavi")));
|
||||
bulkOperations.execute();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewaySingleQueryFlow() {
|
||||
return f -> f
|
||||
.handle(queryOutboundGateway("{name: 'Xavi'}", true))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewaySingleQueryWithTemplateFlow() {
|
||||
return f -> f
|
||||
.handle(queryOutboundGatewayWithTemplate("{name: 'Xavi'}", true))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewaySingleQueryExpressionFlow() {
|
||||
return f -> f
|
||||
.handle(queryExpressionOutboundGateway(true))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewayQueryExpressionFlow() {
|
||||
return f -> f
|
||||
.handle(queryExpressionOutboundGateway(false))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewayQueryExpressionLimitFlow() {
|
||||
return f -> f
|
||||
.handle(queryExpressionOutboundGateway(false, 2))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewayQueryFunctionFlow() {
|
||||
return f -> f
|
||||
.handle(queryFunctionOutboundGateway(true))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewayCollectionNameFunctionFlow() {
|
||||
return f -> f
|
||||
.handle(collectionNameFunctionOutboundGateway(true))
|
||||
.channel(getResultChannel());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageChannel getResultChannel() {
|
||||
return MessageChannels.queue().get();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MongoDbFactory mongoDbFactory() {
|
||||
return new SimpleMongoDbFactory(new MongoClient(), "test");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MongoConverter mongoConverter() {
|
||||
return new TestMongoConverter(mongoDbFactory(), new MongoMappingContext());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MongoOperations mongoTemplate() {
|
||||
return new MongoTemplate(mongoDbFactory());
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryOutboundGateway(String query, boolean expectSingleResult) {
|
||||
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
|
||||
.query(query)
|
||||
.collectionNameExpression("headers.collection")
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryOutboundGatewayWithTemplate(String query, boolean expectSingleResult) {
|
||||
return MongoDb.outboundGateway(mongoTemplate())
|
||||
.query(query)
|
||||
.collectionName(COLLECTION_NAME)
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryExpressionOutboundGateway(boolean expectSingleResult) {
|
||||
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
|
||||
.queryExpression("headers.query")
|
||||
.collectionName(COLLECTION_NAME)
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryExpressionOutboundGateway(boolean expectSingleResult, int maxResults) {
|
||||
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
|
||||
.queryExpression("new BasicQuery('{''address.state'' : ''PA''}').limit(" + maxResults + ")")
|
||||
.collectionName(COLLECTION_NAME)
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryFunctionOutboundGateway(boolean expectSingleResult) {
|
||||
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
|
||||
.queryFunction(msg ->
|
||||
Query.query(Criteria.where("name")
|
||||
.is(msg.getPayload())))
|
||||
.collectionNameExpression("headers.collection")
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec collectionNameFunctionOutboundGateway(boolean expectSingleResult) {
|
||||
return MongoDb.outboundGateway(mongoDbFactory(), mongoConverter())
|
||||
.queryExpression("headers.query")
|
||||
.<String>collectionNameFunction(Message::getPayload)
|
||||
.expectSingleResult(expectSingleResult)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory id="mongoDbFactory" dbname="test" />
|
||||
|
||||
<bean id="mongoDbTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="mongoConverter"
|
||||
class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.TestMongoConverter">
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright 2016 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
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.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailableTests;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbOutboundGatewayTests extends MongoDbAvailableTests {
|
||||
|
||||
private static final String COLLECTION_NAME = "data";
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
private MongoOperations mongoTemplate;
|
||||
|
||||
@Autowired
|
||||
private MongoConverter mongoConverter;
|
||||
|
||||
@Autowired
|
||||
private MongoDbFactory mongoDbFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
BulkOperations bulkOperations = this.mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, COLLECTION_NAME);
|
||||
bulkOperations.insert(Arrays.asList(
|
||||
this.createPerson("Artem"),
|
||||
this.createPerson("Gary"),
|
||||
this.createPerson("Oleg"),
|
||||
this.createPerson("Xavi")));
|
||||
bulkOperations.execute();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mongoTemplate.dropCollection(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testNoFactorySpecified() {
|
||||
MongoDbFactory nullFactory = null;
|
||||
|
||||
try {
|
||||
new MongoDbOutboundGateway(nullFactory);
|
||||
Assert.fail("Expected the test case to throw an IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("MongoDbFactory translator must not be null!", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testNoTemplateSpecified() {
|
||||
MongoOperations mongoTemplate = null;
|
||||
|
||||
try {
|
||||
new MongoDbOutboundGateway(mongoTemplate);
|
||||
Assert.fail("Expected the test case to throw an IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("mongoTemplate must not be null.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testNoQuerySpecified() {
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
|
||||
try {
|
||||
gateway.afterPropertiesSet();
|
||||
gateway.handleRequestMessage(message);
|
||||
Assert.fail("Expected the test case to throw an IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertEquals("no query specified", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testListOfResultsWithQueryExpressionAndLimit() {
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setQueryExpression(
|
||||
PARSER.parseExpression("new BasicQuery('{''address.state'' : ''PA''}').limit(2)"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
List<Person> persons = getPersonsFromResult(result);
|
||||
assertEquals(2, persons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testListOfResultsWithQueryFunction() {
|
||||
Message<String> message = MessageBuilder.withPayload("Xavi").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
Function<Message<String>, Query> queryFunction =
|
||||
msg -> new BasicQuery("{'name' : '" + msg.getPayload() + "'}");
|
||||
FunctionExpression<Message<String>> functionExpression = new FunctionExpression<>(queryFunction);
|
||||
gateway.setQueryExpression(functionExpression);
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
Person person = (Person) result;
|
||||
|
||||
assertEquals("Xavi", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testListOfResultsWithQueryExpressionNotInitialized() {
|
||||
MongoDbOutboundGateway gateway = new MongoDbOutboundGateway(mongoDbFactory);
|
||||
gateway.setBeanFactory(beanFactory);
|
||||
gateway.setMongoConverter(mongoConverter);
|
||||
try {
|
||||
gateway.afterPropertiesSet();
|
||||
Assert.fail("Expected the test case to throw an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertEquals("no query specified", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testListOfResultsWithQueryExpression() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("{}").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.setQueryExpression(PARSER.parseExpression("payload"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
List<Person> persons = getPersonsFromResult(result);
|
||||
assertEquals(4, persons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testListOfResultsWithQueryExpressionReturningOneResult() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("{name : 'Xavi'}").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.setQueryExpression(PARSER.parseExpression("payload"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
List<Person> persons = getPersonsFromResult(result);
|
||||
assertEquals(1, persons.size());
|
||||
assertEquals("Xavi", persons.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleResultWithQueryExpressionAsString() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("{name : 'Artem'}").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setQueryExpression(PARSER.parseExpression("payload"));
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
Person person = (Person) result;
|
||||
assertEquals("Artem", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleResultWithQueryExpressionAsQuery() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setQueryExpression(PARSER.parseExpression("new BasicQuery('{''name'' : ''Gary''}')"));
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
Person person = (Person) result;
|
||||
assertEquals("Gary", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleResultWithQueryExpressionAndNoEntityClass() {
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setQueryExpression(new LiteralExpression("{name : 'Xavi'}"));
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
Document person = (Document) result;
|
||||
assertEquals("Xavi", person.get("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithNullCollectionNameExpression() throws Exception {
|
||||
MongoDbOutboundGateway gateway = new MongoDbOutboundGateway(mongoDbFactory);
|
||||
gateway.setBeanFactory(beanFactory);
|
||||
gateway.setQueryExpression(new LiteralExpression("{name : 'Xavi'}"));
|
||||
gateway.setExpectSingleResult(true);
|
||||
|
||||
try {
|
||||
gateway.afterPropertiesSet();
|
||||
Assert.fail("Expected the test case to throw an IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertEquals("no collection name specified", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithCollectionNameExpressionSpecified() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
MongoDbOutboundGateway gateway = createGateway();
|
||||
gateway.setQueryExpression(new LiteralExpression("{name : 'Xavi'}"));
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.setCollectionNameExpression(new LiteralExpression("anotherCollection"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
Object result = gateway.handleRequestMessage(message);
|
||||
|
||||
assertNull(result);
|
||||
LiteralExpression collectionNameExpression =
|
||||
(LiteralExpression) TestUtils.getPropertyValue(gateway, "collectionNameExpression");
|
||||
assertNotNull(collectionNameExpression);
|
||||
assertEquals("anotherCollection", collectionNameExpression.getValue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Person> getPersonsFromResult(Object result) {
|
||||
return (List<Person>) result;
|
||||
}
|
||||
|
||||
private MongoDbOutboundGateway createGateway() {
|
||||
MongoDbOutboundGateway gateway = new MongoDbOutboundGateway(mongoDbFactory);
|
||||
gateway.setBeanFactory(beanFactory);
|
||||
gateway.setCollectionNameExpression(new LiteralExpression("data"));
|
||||
|
||||
return gateway;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb.xsd">
|
||||
|
||||
<int:channel id="in"/>
|
||||
|
||||
<int:channel id="out">
|
||||
<int:queue capacity="5"/>
|
||||
</int:channel>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewaySingleQuery"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query="{name: 'Xavi'}"
|
||||
collection-name="data"
|
||||
expect-single-result="true"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests$Person"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewayWithTemplate"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{name: 'Xavi'}"
|
||||
collection-name="data"
|
||||
expect-single-result="true"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests$Person"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewaySingleQueryExpression"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query-expression="headers.query"
|
||||
collection-name-expression="headers.collectionName"
|
||||
expect-single-result="true"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests$Person"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewayQueryExpression"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query-expression="headers.query"
|
||||
collection-name-expression="headers.collectionName"
|
||||
expect-single-result="false"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests$Person"/>
|
||||
|
||||
<int-mongodb:outbound-gateway id="gatewayQueryExpressionLimit"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query-expression="new BasicQuery('{''address.state'' : ''PA''}').limit(2)"
|
||||
collection-name-expression="headers.collectionName"
|
||||
expect-single-result="false"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests$Person"/>
|
||||
|
||||
|
||||
<mongo:db-factory id="mongoDbFactory" dbname="test" />
|
||||
|
||||
<bean id="mongoDbTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="mongoConverter"
|
||||
class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.TestMongoConverter">
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2016 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 static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailableTests;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Xavier Padró
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbOutboundGatewayXmlTests extends MongoDbAvailableTests {
|
||||
|
||||
private static final String COLLECTION_NAME = "data";
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
|
||||
|
||||
mongoTemplate.save(this.createPerson("Artem"), COLLECTION_NAME);
|
||||
mongoTemplate.save(this.createPerson("Gary"), COLLECTION_NAME);
|
||||
mongoTemplate.save(this.createPerson("Oleg"), COLLECTION_NAME);
|
||||
mongoTemplate.save(this.createPerson("Xavi"), COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
|
||||
|
||||
mongoTemplate.dropCollection(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleQuery() throws Exception {
|
||||
EventDrivenConsumer consumer = context.getBean("gatewaySingleQuery", EventDrivenConsumer.class);
|
||||
PollableChannel outChannel = context.getBean("out", PollableChannel.class);
|
||||
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
consumer.getHandler().handleMessage(message);
|
||||
|
||||
Message<?> result = outChannel.receive(10000);
|
||||
Person person = getPerson(result);
|
||||
assertEquals("Xavi", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleQueryWithTemplate() throws Exception {
|
||||
EventDrivenConsumer consumer = context.getBean("gatewayWithTemplate", EventDrivenConsumer.class);
|
||||
PollableChannel outChannel = context.getBean("out", PollableChannel.class);
|
||||
|
||||
Message<String> message = MessageBuilder.withPayload("").build();
|
||||
consumer.getHandler().handleMessage(message);
|
||||
|
||||
Message<?> result = outChannel.receive(10000);
|
||||
Person person = getPerson(result);
|
||||
assertEquals("Xavi", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testSingleQueryExpression() throws Exception {
|
||||
EventDrivenConsumer consumer = context.getBean("gatewaySingleQueryExpression", EventDrivenConsumer.class);
|
||||
PollableChannel outChannel = context.getBean("out", PollableChannel.class);
|
||||
|
||||
Message<String> message = MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{'name' : 'Gary'}")
|
||||
.setHeader("collectionName", "data")
|
||||
.build();
|
||||
|
||||
consumer.getHandler().handleMessage(message);
|
||||
|
||||
Message<?> result = outChannel.receive(10000);
|
||||
Person person = getPerson(result);
|
||||
assertEquals("Gary", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testQueryExpression() throws Exception {
|
||||
EventDrivenConsumer consumer = context.getBean("gatewayQueryExpression", EventDrivenConsumer.class);
|
||||
PollableChannel outChannel = context.getBean("out", PollableChannel.class);
|
||||
|
||||
Message<String> message = MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("query", "{}")
|
||||
.setHeader("collectionName", "data")
|
||||
.build();
|
||||
|
||||
consumer.getHandler().handleMessage(message);
|
||||
|
||||
Message<?> result = outChannel.receive(10000);
|
||||
List<Person> persons = getPersons(result);
|
||||
assertEquals(4, persons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testQueryExpressionWithLimit() throws Exception {
|
||||
EventDrivenConsumer consumer = context.getBean("gatewayQueryExpressionLimit", EventDrivenConsumer.class);
|
||||
PollableChannel outChannel = context.getBean("out", PollableChannel.class);
|
||||
|
||||
Message<String> message = MessageBuilder
|
||||
.withPayload("")
|
||||
.setHeader("collectionName", "data")
|
||||
.build();
|
||||
|
||||
consumer.getHandler().handleMessage(message);
|
||||
|
||||
Message<?> result = outChannel.receive(10000);
|
||||
List<Person> persons = getPersons(result);
|
||||
assertEquals(2, persons.size());
|
||||
}
|
||||
|
||||
private Person getPerson(Message<?> message) {
|
||||
return (Person) message.getPayload();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Person> getPersons(Message<?> message) {
|
||||
return (List<Person>) message.getPayload();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,23 +22,23 @@ To connect to MongoDB you can use an implementation of the `MongoDbFactory` inte
|
||||
----
|
||||
public interface MongoDbFactory {
|
||||
|
||||
/**
|
||||
* Creates a default {@link DB} instance.
|
||||
*
|
||||
* @return the DB instance
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
DB getDb() throws DataAccessException;
|
||||
/**
|
||||
* Creates a default {@link DB} instance.
|
||||
*
|
||||
* @return the DB instance
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
DB getDb() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Creates a {@link DB} instance to access the database with the given name.
|
||||
*
|
||||
* @param dbName must not be {@literal null} or empty.
|
||||
*
|
||||
* @return the DB instance
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
DB getDb(String dbName) throws DataAccessException;
|
||||
/**
|
||||
* Creates a {@link DB} instance to access the database with the given name.
|
||||
*
|
||||
* @param dbName must not be {@literal null} or empty.
|
||||
*
|
||||
* @return the DB instance
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
DB getDb(String dbName) throws DataAccessException;
|
||||
}
|
||||
----
|
||||
|
||||
@@ -290,3 +290,120 @@ and other attributes that are common across all other inbound adapters (e.g., 'c
|
||||
The example above is relatively simple and static since it has a literal value for the `collection-name`.
|
||||
Sometimes you may need to change this value at runtime based on some condition.
|
||||
To do that, simply use `collection-name-expression` where the provided expression can be any valid SpEL expression.
|
||||
|
||||
[[mongodb-outbound-gateway]]
|
||||
=== MongoDB Outbound Gateway
|
||||
|
||||
Starting with _version 5.0_, the MongoDb Outbound Gateway is provided and it allows you to query a database by sending a Message to its request channel.
|
||||
The gateway will then send the response to the reply channel.
|
||||
The Message payload and headers can be used to specify the query, as well as collection name.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<int-mongodb:outbound-gateway id="gatewayQuery"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
mongo-converter="mongoConverter"
|
||||
query="{firstName: 'Bob'}"
|
||||
collection-name="foo"
|
||||
request-channel="in"
|
||||
reply-channel="out"
|
||||
entity-class="org.springframework.integration.mongodb.test.entity$Person"/>
|
||||
----
|
||||
|
||||
* `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` to assist 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 have both mongo-template and mongodb-factory set)
|
||||
* `entity-class` - the fully qualified name of the entity class to be passed to `find(..)` or `findOne(..)` method in MongoTemplate.
|
||||
If this attribute is not provided the default value is `org.bson.Document`;
|
||||
* `query` or `query-expression` - specifies the MongoDb query.
|
||||
Please refer to http://www.mongodb.org/display/DOCS/Querying[MongoDB documentation] for more query samples.
|
||||
|
||||
==== Configuring with Java Configuration
|
||||
|
||||
The following Spring Boot application provides an example of configuring the outbound gateway using Java configuration:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
public class MongoDbJavaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(MongoDbJavaApplication.class)
|
||||
.web(false)
|
||||
.run(args);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MongoDbFactory mongoDbFactory;
|
||||
|
||||
@Bean
|
||||
public MessageChannel requestChannel() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageChannel replyChannel() {
|
||||
return new QueueChannel(5);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "requestChannel")
|
||||
public MessageHandler mongoDbOutboundGateway() {
|
||||
MongoDbOutboundGateway gateway = new MongoDbOutboundGateway(this.mongoDbFactory);
|
||||
gateway.setCollectionNameExpressionString("'foo'");
|
||||
gateway.setQueryExpressionString("'{''name'' : ''Bob''}'");
|
||||
gateway.setExpectSingleResult(true);
|
||||
gateway.setEntityClass(Person.class);
|
||||
gateway.setOutputChannelName("replyChannel");
|
||||
|
||||
return gateway;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "replyChannel")
|
||||
public MessageHandler handler() {
|
||||
return message -> System.out.println(message.getPayload());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Configuring with the Java DSL
|
||||
|
||||
The following Spring Boot application provides an example of configuring the Outbound Gateway using the Java DSL:
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
public class MongoDbJavaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(MongoDbJavaApplication.class)
|
||||
.web(false)
|
||||
.run(args);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MongoDbFactory;
|
||||
|
||||
@Autowired
|
||||
private MongoConverter;
|
||||
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow gatewaySingleQueryFlow() {
|
||||
return f -> f
|
||||
.handle(queryOutboundGateway())
|
||||
.channel(c -> c.queue("retrieveResults"));
|
||||
}
|
||||
|
||||
private MongoDbOutboundGatewaySpec queryOutboundGateway() {
|
||||
return MongoDb.outboundGateway(this.mongoDbFactory, this.mongoConverter)
|
||||
.query("{name : 'Bob'}")
|
||||
.collectionNameFunction(m -> m.getHeaders().get("collection"))
|
||||
.expectSingleResult(true)
|
||||
.entityClass(Person.class);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
@@ -9,6 +9,10 @@ development process.
|
||||
[[x5.0-new-components]]
|
||||
=== New Components
|
||||
|
||||
==== MongoDB Outbound Gateway
|
||||
|
||||
The new `MongoDbOutboundGateway` allows you to make queries to the database on demand by sending a message to its request channel.
|
||||
See <<mongodb-outbound-gateway>> for more information.
|
||||
|
||||
[[x5.0-general]]
|
||||
=== General Changes
|
||||
|
||||
Reference in New Issue
Block a user