RESOLVED - issue INT-1102: Add timestamp to JdbcMessageStore

This commit is contained in:
David Syer
2010-04-27 12:15:21 +00:00
parent 42113a497c
commit bfbf660ea3
7 changed files with 65 additions and 42 deletions

View File

@@ -55,6 +55,12 @@
<artifactId>spring-integration-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
@@ -87,5 +93,11 @@
<version>1.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -6,6 +6,7 @@ import java.security.NoSuchAlgorithmException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
import java.util.UUID;
@@ -45,14 +46,14 @@ public class JdbcMessageStore implements MessageStore {
*/
public static final String DEFAULT_TABLE_PREFIX = "INT_";
private static final String LIST_MESSAGES_BY_CORRELATION_KEY = "SELECT MESSAGE_ID, CORRELATION_KEY, MESSAGE_BYTES from %PREFIX%MESSAGE where CORRELATION_KEY=?";
private static final String LIST_MESSAGES_BY_CORRELATION_KEY = "SELECT MESSAGE_ID, CREATED_DATE, CORRELATION_KEY, MESSAGE_BYTES from %PREFIX%MESSAGE where CORRELATION_KEY=?";
private static final String GET_MESSAGE = "SELECT MESSAGE_ID, CORRELATION_KEY, MESSAGE_BYTES from %PREFIX%MESSAGE where MESSAGE_ID=?";
private static final String GET_MESSAGE = "SELECT MESSAGE_ID, CREATED_DATE, CORRELATION_KEY, MESSAGE_BYTES from %PREFIX%MESSAGE where MESSAGE_ID=?";
private static final String DELETE_MESSAGE = "DELETE from %PREFIX%MESSAGE where MESSAGE_ID=?";
private static final String CREATE_MESSAGE = "INSERT into %PREFIX%MESSAGE(MESSAGE_ID, CORRELATION_KEY, MESSAGE_BYTES)"
+ " values (?, ?, ?)";
private static final String CREATE_MESSAGE = "INSERT into %PREFIX%MESSAGE(MESSAGE_ID, CREATED_DATE, CORRELATION_KEY, MESSAGE_BYTES)"
+ " values (?, ?, ?, ?)";
public static final int DEFAULT_LONG_STRING_LENGTH = 2500;
@@ -62,6 +63,12 @@ public class JdbcMessageStore implements MessageStore {
*/
public static final String SAVED_KEY = JdbcMessageStore.class.getSimpleName() + ".SAVED";
/**
* The name of the message header that stores a timestamp for the time the
* message was inserted.
*/
public static final String CREATED_DATE_KEY = JdbcMessageStore.class.getSimpleName() + ".CREATED_DATE";
private String tablePrefix = DEFAULT_TABLE_PREFIX;
private JdbcOperations jdbcTemplate;
@@ -192,7 +199,9 @@ public class JdbcMessageStore implements MessageStore {
}
}
Message<T> result = MessageBuilder.fromMessage(message).setHeader(SAVED_KEY, Boolean.TRUE).build();
final long createdDate = System.currentTimeMillis();
Message<T> result = MessageBuilder.fromMessage(message).setHeader(SAVED_KEY, Boolean.TRUE).setHeader(
CREATED_DATE_KEY, new Long(createdDate)).build();
final String messageId = getKey(result.getHeaders().getId());
final String correlationId = getKey(result.getHeaders().getCorrelationId());
final byte[] messageBytes = SerializationUtils.serialize(result);
@@ -201,8 +210,9 @@ public class JdbcMessageStore implements MessageStore {
public void setValues(PreparedStatement ps) throws SQLException {
logger.debug("Inserting message with id key=" + messageId);
ps.setString(1, messageId);
ps.setString(2, correlationId);
lobHandler.getLobCreator().setBlobAsBytes(ps, 3, messageBytes);
ps.setTimestamp(2, new Timestamp(createdDate));
ps.setString(3, correlationId);
lobHandler.getLobCreator().setBlobAsBytes(ps, 4, messageBytes);
}
});

View File

@@ -1,5 +1,6 @@
CREATE TABLE INT_MESSAGE (
MESSAGE_ID VARCHAR(100) NOT NULL PRIMARY KEY,
CREATED_DATE TIMESTAMP NOT NULL,
CORRELATION_KEY VARCHAR(100),
MESSAGE_BYTES BLOB
);

View File

@@ -5,7 +5,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.springframework.integration.test.matcher.PayloadAndHeaderMatcher.sameExceptImmutableHeaders;
import static org.springframework.integration.test.matcher.PayloadAndHeaderMatcher.sameExceptIgnorableHeaders;
import java.util.UUID;
@@ -50,7 +50,9 @@ public class JdbcMessageStoreTests {
assertNull(messageStore.get(message.getHeaders().getId()));
Message<?> result = messageStore.get(saved.getHeaders().getId());
assertNotNull(result);
assertThat(saved, sameExceptImmutableHeaders(result));
assertThat(saved, sameExceptIgnorableHeaders(result));
assertNotNull(result.getHeaders().get(JdbcMessageStore.SAVED_KEY));
assertNotNull(result.getHeaders().get(JdbcMessageStore.CREATED_DATE_KEY));
}
@Test
@@ -80,7 +82,7 @@ public class JdbcMessageStoreTests {
Message<String> copy = MessageBuilder.fromMessage(saved).build();
Message<String> result = messageStore.put(copy);
assertNotSame(copy, result);
assertThat(saved, sameExceptImmutableHeaders(result));
assertThat(saved, sameExceptIgnorableHeaders(result, JdbcMessageStore.CREATED_DATE_KEY));
assertNotNull(messageStore.get(saved.getHeaders().getId()));
}

View File

@@ -1,26 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java" />
<classpathentry kind="src" path="src/main/resources" />
<classpathentry kind="src" output="target/test-classes" path="src/test/java" />
<classpathentry kind="src" path="src/test/resources" />
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-1.6.5.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.5.RELEASE/com.springsource.org.aspectj.weaver-1.6.5.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-2.1.3.jar" sourcepath="/SI_IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/SI_IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/SI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.aop/3.0.2.RELEASE/org.springframework.aop-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.aop/3.0.2.RELEASE/org.springframework.aop-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.asm/3.0.2.RELEASE/org.springframework.asm-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.asm/3.0.2.RELEASE/org.springframework.asm-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.beans/3.0.2.RELEASE/org.springframework.beans-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.beans/3.0.2.RELEASE/org.springframework.beans-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.context/3.0.2.RELEASE/org.springframework.context-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.context/3.0.2.RELEASE/org.springframework.context-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.context.support/3.0.2.RELEASE/org.springframework.context.support-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.context.support/3.0.2.RELEASE/org.springframework.context.support-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.core/3.0.2.RELEASE/org.springframework.core-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.core/3.0.2.RELEASE/org.springframework.core-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.expression/3.0.2.RELEASE/org.springframework.expression-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.expression/3.0.2.RELEASE/org.springframework.expression-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.transaction/3.0.2.RELEASE/org.springframework.transaction-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.transaction/3.0.2.RELEASE/org.springframework.transaction-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.springframework/org.springframework.test/3.0.2.RELEASE/org.springframework.test-3.0.2.RELEASE.jar" sourcepath="/SI_IVY_CACHE/org.springframework/org.springframework.test/3.0.2.RELEASE/org.springframework.test-sources-3.0.2.RELEASE.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.mockito/com.springsource.org.mockito/1.8.0/com.springsource.org.mockito-1.8.0.jar" sourcepath="/SI_IVY_CACHE/org.mockito/com.springsource.org.mockito/1.8.0/com.springsource.org.mockito-sources-1.8.0.jar" />
<classpathentry kind="var" path="SI_IVY_CACHE/org.objenesis/com.springsource.org.objenesis/1.0.0/com.springsource.org.objenesis-1.0.0.jar" sourcepath="/SI_IVY_CACHE/org.objenesis/com.springsource.org.objenesis/1.0.0/com.springsource.org.objenesis-sources-1.0.0.jar" />
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.integration" />
<classpathentry kind="output" path="target/classes" />
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.springframework.integration.test</name>
<name>spring-integration-test</name>
<comment></comment>
<projects>
</projects>
@@ -15,8 +15,14 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>

View File

@@ -14,7 +14,7 @@ import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageHeaders;
/**
* Matcher to make assertions about message equality easier. Usage:
* Matcher to make assertions about message equality easier. Usage:
*
* <pre>
* &#064;Test
@@ -29,21 +29,25 @@ import org.springframework.integration.core.MessageHeaders;
* return new PayloadAndHeaderMatcher(expected);
* }
* </pre>
*
*
* @author Dave Syer
*
*
*/
public class PayloadAndHeaderMatcher extends BaseMatcher<Message<?>> {
private final Object payload;
private final Map<String, Object> headers;
private final String[] ignoreKeys;
@Factory
public static Matcher<Message<?>> sameExceptImmutableHeaders(Message<?> expected) {
return new PayloadAndHeaderMatcher(expected);
public static Matcher<Message<?>> sameExceptIgnorableHeaders(Message<?> expected, String... ignoreKeys) {
return new PayloadAndHeaderMatcher(expected, ignoreKeys);
}
private PayloadAndHeaderMatcher(Message<?> expected) {
private PayloadAndHeaderMatcher(Message<?> expected, String... ignoreKeys) {
this.ignoreKeys = ignoreKeys;
this.payload = expected.getPayload();
this.headers = getHeaders(expected);
}
@@ -52,6 +56,9 @@ public class PayloadAndHeaderMatcher extends BaseMatcher<Message<?>> {
HashMap<String, Object> headers = new HashMap<String, Object>(operand.getHeaders());
headers.remove(MessageHeaders.ID);
headers.remove(MessageHeaders.TIMESTAMP);
for (String key : ignoreKeys) {
headers.remove(key);
}
return headers;
}
@@ -62,7 +69,8 @@ public class PayloadAndHeaderMatcher extends BaseMatcher<Message<?>> {
}
public void describeTo(Description description) {
description.appendText("a Message with Headers that match except ID and timestamp for payload: ").appendValue(payload).appendText(" and headers: ").appendValue(headers);
description.appendText("a Message with Headers that match except ID and timestamp for payload: ").appendValue(
payload).appendText(" and headers: ").appendValue(headers);
}
}