INT-4163: UnProxy MessageSource for TX Resource
JIRA: https://jira.spring.io/browse/INT-4163 When `MessageSource` is proxy, the `TransactionSynchronizationManager.getResource(this)` logic in the `MessageSource` doesn't work, because TX resource is bound to the `Proxy` in the `SourcePollingChannelAdapter` * Introduce `SourcePollingChannelAdapter.originalSource` property and store there a target `MessageSource` object extracted from the AOP Proxy * Use `originalSource` as a resource to bind to the TX * Modify `MongoDbInboundChannelAdapterIntegrationTests` to ensure that `AbstractMessageSourceAdvice` proxying the `MessageSource` doesn't effect `TransactionSynchronizationManager.getResource(this)` logic * Refactor for some MongoDb test to rely on the `@RunWith(SpringJUnit4ClassRunner.class)` for context loading for better test class performance **Cherry-pick to 4.3.x, 4.2.x** Fallback to provided source if `target` from Proxy is `null` Fix [UnusedImport] issue
This commit is contained in:
committed by
Gary Russell
parent
acf7424dbc
commit
e2d18054e6
@@ -25,6 +25,7 @@ import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.aop.AbstractMessageSourceAdvice;
|
||||
import org.springframework.integration.context.ExpressionCapable;
|
||||
@@ -55,6 +56,8 @@ public class SourcePollingChannelAdapter extends AbstractPollingEndpoint
|
||||
|
||||
private final Collection<Advice> appliedAdvices = new HashSet<Advice>();
|
||||
|
||||
private volatile MessageSource<?> originalSource;
|
||||
|
||||
private volatile MessageSource<?> source;
|
||||
|
||||
private volatile MessageChannel outputChannel;
|
||||
@@ -70,6 +73,10 @@ public class SourcePollingChannelAdapter extends AbstractPollingEndpoint
|
||||
*/
|
||||
public void setSource(MessageSource<?> source) {
|
||||
this.source = source;
|
||||
|
||||
Object target = extractProxyTarget(source);
|
||||
this.originalSource = target != null ? (MessageSource<?>) target : source;
|
||||
|
||||
if (source instanceof ExpressionCapable) {
|
||||
setPrimaryExpression(((ExpressionCapable) source).getExpression());
|
||||
}
|
||||
@@ -219,7 +226,7 @@ public class SourcePollingChannelAdapter extends AbstractPollingEndpoint
|
||||
|
||||
@Override
|
||||
protected Object getResourceToBind() {
|
||||
return this.source;
|
||||
return this.originalSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,4 +234,21 @@ public class SourcePollingChannelAdapter extends AbstractPollingEndpoint
|
||||
return IntegrationResourceHolder.MESSAGE_SOURCE;
|
||||
}
|
||||
|
||||
private static Object extractProxyTarget(Object target) {
|
||||
if (!(target instanceof Advised)) {
|
||||
return target;
|
||||
}
|
||||
Advised advised = (Advised) target;
|
||||
if (advised.getTargetSource() == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return extractProxyTarget(advised.getTargetSource().getTarget());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new BeanCreationException("Could not extract target", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
<?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"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
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
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
|
||||
|
||||
<mongo:db-factory id="mongoDbFactory" dbname="test" />
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapter"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="100" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterNamedFactory"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithTemplate"
|
||||
channel="replyChannel"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
expect-single-result="true"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.Person"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithNamedCollection"
|
||||
channel="replyChannel"
|
||||
collection-name="foo"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithNamedCollectionExpression"
|
||||
channel="replyChannel"
|
||||
collection-name-expression="'foo'"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="inboundAdapterWithOnSuccessDisposition"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
auto-startup="false">
|
||||
|
||||
<int:poller fixed-rate="200" max-messages-per-poll="1">
|
||||
<int:advice-chain synchronization-factory="syncFactory">
|
||||
<bean
|
||||
class="org.springframework.integration.mongodb.config.MongoDbInboundChannelAdapterIntegrationTests.TestMessageSourceAdvice" />
|
||||
<tx:advice>
|
||||
<tx:attributes>
|
||||
<tx:method name="*" />
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
</int:advice-chain>
|
||||
</int:poller>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int:transaction-synchronization-factory id="syncFactory">
|
||||
<int:after-commit expression="@documentCleaner.remove(#mongoTemplate, payload, headers.mongo_collectionName)" />
|
||||
</int:transaction-synchronization-factory>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithConverter"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
mongo-converter="mongoConverter"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="100" />
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<bean id="documentCleaner"
|
||||
class="org.springframework.integration.mongodb.config.MongoDbInboundChannelAdapterIntegrationTests.DocumentCleaner" />
|
||||
|
||||
<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>
|
||||
|
||||
<int:channel id="replyChannel">
|
||||
<int:queue />
|
||||
</int:channel>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager" />
|
||||
|
||||
</beans>
|
||||
@@ -22,174 +22,181 @@ import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
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.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
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.query.BasicQuery;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.integration.aop.AbstractMessageSourceAdvice;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailable;
|
||||
import org.springframework.integration.mongodb.rules.MongoDbAvailableTests;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
* @since 2.2
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbInboundChannelAdapterIntegrationTests extends MongoDbAvailableTests {
|
||||
|
||||
@Autowired
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel replyChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapter")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapter;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapterNamedFactory")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapterNamedFactory;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapterWithTemplate")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapterWithTemplate;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapterWithNamedCollection")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapterWithNamedCollection;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapterWithNamedCollectionExpression")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapterWithNamedCollectionExpression;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("inboundAdapterWithOnSuccessDisposition")
|
||||
private SourcePollingChannelAdapter inboundAdapterWithOnSuccessDisposition;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoInboundAdapterWithConverter")
|
||||
private SourcePollingChannelAdapter mongoInboundAdapterWithConverter;
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithDefaultMongoFactory() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "data");
|
||||
this.mongoTemplate.save(createPerson("Bob"), "data");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapter", SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapter.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<Person>> message = (Message<List<Person>>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().get(0).getName());
|
||||
assertNotNull(replyChannel.receive(10000));
|
||||
context.close();
|
||||
assertNotNull(this.replyChannel.receive(10000));
|
||||
|
||||
this.mongoInboundAdapter.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithNamedMongoFactory() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "data");
|
||||
this.mongoTemplate.save(this.createPerson("Bob"), "data");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapterNamedFactory",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapterNamedFactory.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<DBObject>> message = (Message<List<DBObject>>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().get(0).get("name"));
|
||||
context.close();
|
||||
|
||||
this.mongoInboundAdapterNamedFactory.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithMongoTemplate() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "data");
|
||||
this.mongoTemplate.save(this.createPerson("Bob"), "data");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapterWithTemplate",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapterWithTemplate.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<Person> message = (Message<Person>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().getName());
|
||||
context.close();
|
||||
|
||||
this.mongoInboundAdapterWithTemplate.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithNamedCollection() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "foo");
|
||||
this.mongoTemplate.save(this.createPerson("Bob"), "foo");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapterWithNamedCollection",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapterWithNamedCollection.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<Person>> message = (Message<List<Person>>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().get(0).getName());
|
||||
context.close();
|
||||
|
||||
this.mongoInboundAdapterWithNamedCollection.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithNamedCollectionExpression() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "foo");
|
||||
this.mongoTemplate.save(this.createPerson("Bob"), "foo");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapterWithNamedCollectionExpression",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapterWithNamedCollectionExpression.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<Person>> message = (Message<List<Person>>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().get(0).getName());
|
||||
context.close();
|
||||
|
||||
this.mongoInboundAdapterWithNamedCollectionExpression.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithOnSuccessDisposition() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "data");
|
||||
this.mongoTemplate.save(createPerson("Bob"), "data");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("inboundAdapterWithOnSuccessDisposition",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.inboundAdapterWithOnSuccessDisposition.start();
|
||||
|
||||
assertNotNull(replyChannel.receive(10000));
|
||||
Thread.sleep(300);
|
||||
assertNull(replyChannel.receive(100));
|
||||
context.close();
|
||||
|
||||
this.inboundAdapterWithOnSuccessDisposition.stop();
|
||||
|
||||
assertNull(this.mongoTemplate.findOne(new Query(Criteria.where("name").is("Bob")), Person.class, "data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@MongoDbAvailable
|
||||
public void testWithMongoConverter() throws Exception {
|
||||
MongoDbFactory mongoDbFactory = this.prepareMongoFactory();
|
||||
MongoTemplate template = new MongoTemplate(mongoDbFactory);
|
||||
template.save(this.createPerson("Bob"), "data");
|
||||
this.mongoTemplate.save(this.createPerson("Bob"), "data");
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("mongoInboundAdapterWithConverter",
|
||||
SourcePollingChannelAdapter.class);
|
||||
QueueChannel replyChannel = context.getBean("replyChannel", QueueChannel.class);
|
||||
spca.start();
|
||||
this.mongoInboundAdapterWithConverter.start();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<Person>> message = (Message<List<Person>>) replyChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Bob", message.getPayload().get(0).getName());
|
||||
assertNotNull(replyChannel.receive(10000));
|
||||
context.close();
|
||||
|
||||
this.mongoInboundAdapterWithConverter.stop();
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
@@ -206,7 +213,7 @@ public class MongoDbInboundChannelAdapterIntegrationTests extends MongoDbAvailab
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
@MongoDbAvailable
|
||||
public void testFailureWithCollectionAndCollectioinExpression() throws Exception {
|
||||
public void testFailureWithCollectionAndCollectionExpression() throws Exception {
|
||||
new ClassPathXmlApplicationContext("inbound-fail-c-cex.xml", this.getClass()).close();
|
||||
}
|
||||
|
||||
@@ -229,4 +236,18 @@ public class MongoDbInboundChannelAdapterIntegrationTests extends MongoDbAvailab
|
||||
|
||||
}
|
||||
|
||||
public static final class TestMessageSourceAdvice extends AbstractMessageSourceAdvice {
|
||||
|
||||
@Override
|
||||
public boolean beforeReceive(MessageSource<?> source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message<?> afterReceive(Message<?> result, MessageSource<?> source) {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,87 +18,115 @@ package org.springframework.integration.mongodb.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
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.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
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.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.mongodb.inbound.MongoDbMessageSource;
|
||||
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.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class MongoDbInboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
private MongoDbFactory mongoDbFactory;
|
||||
|
||||
@Autowired
|
||||
private MongoConverter mongoConverter;
|
||||
|
||||
@Autowired
|
||||
private MongoTemplate mongoDbTemplate;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("minimalConfig.adapter")
|
||||
private SourcePollingChannelAdapter minimalConfigAdapter;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("fullConfigWithCollectionExpression.adapter")
|
||||
private SourcePollingChannelAdapter fullConfigWithCollectionExpressionAdapter;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("fullConfigWithCollectionName.adapter")
|
||||
private SourcePollingChannelAdapter fullConfigWithCollectionNameAdapter;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("fullConfigWithMongoTemplate.adapter")
|
||||
private SourcePollingChannelAdapter fullConfigWithMongoTemplateAdapter;
|
||||
|
||||
@Test
|
||||
public void minimalConfig() {
|
||||
ClassPathXmlApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-parser-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("minimalConfig.adapter", SourcePollingChannelAdapter.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(spca, "source", MongoDbMessageSource.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(this.minimalConfigAdapter, "source",
|
||||
MongoDbMessageSource.class);
|
||||
|
||||
assertEquals(false, TestUtils.getPropertyValue(spca, "shouldTrack"));
|
||||
assertEquals(false, TestUtils.getPropertyValue(this.minimalConfigAdapter, "shouldTrack"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertEquals(context.getBean("mongoDbFactory"), TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertEquals(this.mongoDbFactory, TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(source, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("data", TestUtils.getPropertyValue(source, "collectionNameExpression.literalValue"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithCollectionExpression() {
|
||||
ClassPathXmlApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-parser-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("fullConfigWithCollectionExpression.adapter", SourcePollingChannelAdapter.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(spca, "source", MongoDbMessageSource.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(this.fullConfigWithCollectionExpressionAdapter,
|
||||
"source", MongoDbMessageSource.class);
|
||||
|
||||
assertEquals(false, TestUtils.getPropertyValue(spca, "shouldTrack"));
|
||||
assertEquals(false, TestUtils.getPropertyValue(this.fullConfigWithCollectionExpressionAdapter, "shouldTrack"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertEquals(context.getBean("mongoDbFactory"), TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertEquals(context.getBean("mongoConverter"), TestUtils.getPropertyValue(source, "mongoConverter"));
|
||||
assertEquals(this.mongoDbFactory, TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertEquals(this.mongoConverter, TestUtils.getPropertyValue(source, "mongoConverter"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(source, "collectionNameExpression") instanceof SpelExpression);
|
||||
assertEquals("'foo'", TestUtils.getPropertyValue(source, "collectionNameExpression.expression"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithCollectionName() {
|
||||
ClassPathXmlApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-parser-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("fullConfigWithCollectionName.adapter", SourcePollingChannelAdapter.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(spca, "source", MongoDbMessageSource.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(this.fullConfigWithCollectionNameAdapter, "source",
|
||||
MongoDbMessageSource.class);
|
||||
|
||||
assertEquals(false, TestUtils.getPropertyValue(spca, "shouldTrack"));
|
||||
assertEquals(false, TestUtils.getPropertyValue(this.fullConfigWithCollectionNameAdapter, "shouldTrack"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertEquals(context.getBean("mongoDbFactory"), TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertEquals(context.getBean("mongoConverter"), TestUtils.getPropertyValue(source, "mongoConverter"));
|
||||
assertEquals(this.mongoDbFactory, TestUtils.getPropertyValue(source, "mongoDbFactory"));
|
||||
assertEquals(this.mongoConverter, TestUtils.getPropertyValue(source, "mongoConverter"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(source, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(source, "collectionNameExpression.literalValue"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fullConfigWithMongoTemplate() {
|
||||
ClassPathXmlApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-parser-config.xml", this.getClass());
|
||||
SourcePollingChannelAdapter spca = context.getBean("fullConfigWithMongoTemplate.adapter", SourcePollingChannelAdapter.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(spca, "source", MongoDbMessageSource.class);
|
||||
MongoDbMessageSource source = TestUtils.getPropertyValue(this.fullConfigWithMongoTemplateAdapter, "source",
|
||||
MongoDbMessageSource.class);
|
||||
|
||||
assertEquals(false, TestUtils.getPropertyValue(spca, "shouldTrack"));
|
||||
assertEquals(false, TestUtils.getPropertyValue(this.fullConfigWithMongoTemplateAdapter, "shouldTrack"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertEquals(context.getBean("mongoDbTemplate"), TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertSame(this.mongoDbTemplate, TestUtils.getPropertyValue(source, "mongoTemplate"));
|
||||
assertNotNull(TestUtils.getPropertyValue(source, "evaluationContext"));
|
||||
assertTrue(TestUtils.getPropertyValue(source, "collectionNameExpression") instanceof LiteralExpression);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(source, "collectionNameExpression.literalValue"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
@@ -112,4 +140,5 @@ public class MongoDbInboundChannelAdapterParserTests {
|
||||
new ClassPathXmlApplicationContext("inbound-adapter-parser-fail-template-converter-config.xml", this.getClass())
|
||||
.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
<?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">
|
||||
|
||||
<mongo:db-factory id="mongoDbFactory" dbname="test"/>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapter"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="100"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterNamedFactory"
|
||||
mongodb-factory="mongoDbFactory"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithTemplate"
|
||||
channel="replyChannel"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
expect-single-result="true"
|
||||
entity-class="org.springframework.integration.mongodb.rules.MongoDbAvailableTests.Person"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithNamedCollection"
|
||||
channel="replyChannel"
|
||||
collection-name="foo"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithNamedCollectionExpression"
|
||||
channel="replyChannel"
|
||||
collection-name-expression="'foo'"
|
||||
mongo-template="mongoDbTemplate"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="5000"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="inboundAdapterWithOnSuccessDisposition"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
auto-startup="false">
|
||||
|
||||
<int:poller fixed-rate="200" max-messages-per-poll="1">
|
||||
<int:transactional synchronization-factory="syncFactory"/>
|
||||
</int:poller>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<int:transaction-synchronization-factory id="syncFactory">
|
||||
<int:after-commit expression="@documentCleaner.remove(#mongoTemplate, payload, headers.mongo_collectionName)"/>
|
||||
</int:transaction-synchronization-factory>
|
||||
|
||||
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapterWithConverter"
|
||||
channel="replyChannel"
|
||||
query="{'name' : 'Bob'}"
|
||||
entity-class="java.lang.Object"
|
||||
mongo-converter="mongoConverter"
|
||||
auto-startup="false">
|
||||
<int:poller fixed-rate="100"/>
|
||||
</int-mongodb:inbound-channel-adapter>
|
||||
|
||||
<bean id="documentCleaner" class="org.springframework.integration.mongodb.config.MongoDbInboundChannelAdapterIntegrationTests.DocumentCleaner"/>
|
||||
|
||||
<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>
|
||||
|
||||
<int:channel id="replyChannel">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.integration.transaction.PseudoTransactionManager"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user