INT-1069: Add MessageGroupQueue and JDBC tests for rollback
This commit is contained in:
11
spring-integration-jdbc/src/test/java/log4j.properties
Normal file
11
spring-integration-jdbc/src/test/java/log4j.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
log4j.rootCategory=WARN, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
|
||||
|
||||
|
||||
log4j.category.org.springframework=WARN
|
||||
log4j.category.org.springframework.integration=DEBUG
|
||||
log4j.category.org.springframework.integration.jdbc=WARN
|
||||
log4j.category.org.springframework.jdbc=DEBUG
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.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/jdbc http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd">
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="DERBY">
|
||||
<jdbc:script location="${int.schema.script}" />
|
||||
</jdbc:embedded-database>
|
||||
|
||||
<int-jdbc:message-store id="messageStore" data-source="dataSource" />
|
||||
|
||||
<channel id="input" xmlns="http://www.springframework.org/schema/integration">
|
||||
<queue ref="queue"/>
|
||||
</channel>
|
||||
|
||||
<int:channel id="output"/>
|
||||
|
||||
<int:logging-channel-adapter channel="output"/>
|
||||
|
||||
<bean id="queue" class="org.springframework.integration.store.MessageGroupQueue">
|
||||
<constructor-arg ref="messageStore" />
|
||||
<constructor-arg value="input-queue" />
|
||||
</bean>
|
||||
|
||||
<service-activator id="service-activator" input-channel="input" output-channel="output" xmlns="http://www.springframework.org/schema/integration">
|
||||
<beans:bean class="org.springframework.integration.jdbc.JdbcMessageStoreChannelTests$Service" />
|
||||
<poller>
|
||||
<interval-trigger interval="200"/>
|
||||
<transactional />
|
||||
</poller>
|
||||
</service-activator>
|
||||
|
||||
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
||||
<property name="location" value="classpath:int-${ENVIRONMENT:derby}.properties" />
|
||||
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
|
||||
<property name="ignoreUnresolvablePlaceholders" value="true" />
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,95 @@
|
||||
package org.springframework.integration.jdbc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class JdbcMessageStoreChannelTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private JdbcMessageStore messageStore;
|
||||
|
||||
@Before
|
||||
public void clear() {
|
||||
for (MessageGroup group : messageStore) {
|
||||
messageStore.removeMessageGroup(group.getCorrelationKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndActivate() throws Exception {
|
||||
Service.reset(1);
|
||||
input.send(new StringMessage("foo"));
|
||||
Service.await(1000);
|
||||
assertEquals(1, Service.messages.size());
|
||||
assertEquals(0, messageStore.getMessageGroup("input-queue").size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndActivateWithRollback() throws Exception {
|
||||
Service.reset(1);
|
||||
Service.fail = true;
|
||||
input.send(new StringMessage("foo"));
|
||||
Service.await(1000);
|
||||
assertEquals(1, Service.messages.size());
|
||||
// After a rollback in the poller the message is still waiting to be delivered
|
||||
assertEquals(1, messageStore.getMessageGroup("input-queue").size());
|
||||
assertEquals(1, messageStore.getMessageGroup("input-queue").getUnmarked().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testSendAndActivateTransactionalSend() throws Exception {
|
||||
Service.reset(1);
|
||||
input.send(new StringMessage("foo"));
|
||||
// This will time out because the transaction has not committed yet
|
||||
Service.await(1000);
|
||||
// So no activation
|
||||
assertEquals(0, Service.messages.size());
|
||||
// But inside the transaction the message is still there
|
||||
assertEquals(1, messageStore.getMessageGroup("input-queue").size());
|
||||
assertEquals(1, messageStore.getMessageGroup("input-queue").getUnmarked().size());
|
||||
}
|
||||
|
||||
public static class Service {
|
||||
private static boolean fail = false;
|
||||
private static List<String> messages = new ArrayList<String>();
|
||||
private static CountDownLatch latch = new CountDownLatch(0);
|
||||
public static void reset(int count) {
|
||||
fail = false;
|
||||
messages.clear();
|
||||
latch = new CountDownLatch(count);
|
||||
}
|
||||
public static void await(long timeout) throws InterruptedException {
|
||||
latch.await(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
public String echo(String input) {
|
||||
latch.countDown();
|
||||
messages.add(input);
|
||||
if (fail) {
|
||||
throw new RuntimeException("Planned failure");
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="DERBY">
|
||||
|
||||
@@ -8,6 +8,7 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.integration.test.matcher.PayloadAndHeaderMatcher.sameExceptIgnorableHeaders;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
@@ -19,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.integration.store.MessageGroupCallback;
|
||||
import org.springframework.integration.store.MessageGroupStore;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -100,7 +103,7 @@ public class JdbcMessageStoreTests {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testAddAndDelete() throws Exception {
|
||||
public void testAddAndRemoveMessageGroup() throws Exception {
|
||||
Message<String> message = MessageBuilder.withPayload("foo").build();
|
||||
message = messageStore.addMessage(message);
|
||||
assertNotNull(messageStore.removeMessage(message.getHeaders().getId()));
|
||||
@@ -118,6 +121,32 @@ public class JdbcMessageStoreTests {
|
||||
assertTrue("Timestamp too early: " + group.getTimestamp() + "<" + now, group.getTimestamp() >= now);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testAddAndRemoveMessageFromMessageGroup() throws Exception {
|
||||
String correlationId = "X";
|
||||
Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(correlationId).build();
|
||||
messageStore.addMessageToGroup(correlationId, message);
|
||||
messageStore.removeMessageFromGroup(correlationId, message);
|
||||
MessageGroup group = messageStore.getMessageGroup(correlationId);
|
||||
assertEquals(0, group.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testOrderInMessageGroup() throws Exception {
|
||||
String correlationId = "X";
|
||||
Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(correlationId).build();
|
||||
messageStore.addMessageToGroup(correlationId, message);
|
||||
message = MessageBuilder.withPayload("bar").setCorrelationId(correlationId).build();
|
||||
messageStore.addMessageToGroup(correlationId, message);
|
||||
MessageGroup group = messageStore.getMessageGroup(correlationId);
|
||||
assertEquals(2, group.size());
|
||||
Iterator<Message<?>> iterator = group.getUnmarked().iterator();
|
||||
assertEquals("foo", iterator.next().getPayload());
|
||||
assertEquals("bar", iterator.next().getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testAddAndMarkMessageGroup() throws Exception {
|
||||
@@ -135,9 +164,14 @@ public class JdbcMessageStoreTests {
|
||||
String correlationId = "X";
|
||||
Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(correlationId).build();
|
||||
messageStore.addMessageToGroup(correlationId, message);
|
||||
messageStore.registerMessageGroupExpiryCallback(new MessageGroupCallback() {
|
||||
public void execute(MessageGroupStore messageGroupStore, MessageGroup group) {
|
||||
messageGroupStore.removeMessageGroup(group.getCorrelationKey());
|
||||
}
|
||||
});
|
||||
messageStore.expireMessageGroups(-10000);
|
||||
MessageGroup group = messageStore.getMessageGroup(correlationId);
|
||||
assertEquals(0, group.getMarked().size());
|
||||
assertEquals(0, group.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user