INT-2460: Remove Message Modification Logic in MS
JIRA: https://jira.spring.io/browse/INT-2460, https://jira.spring.io/browse/INT-4122 Since the main purpose of the `MessageStore` to persist message for durability and only, it doesn't make sense to modify `Message` for additional headers like `SAVED` and `CREATED_DATE`. Such a logic should be a part of metadata stored together with the message. And it is provided by the out-of-the-box `MessageStore` implementation. In addition we free ourselves from the reflection operations to retain `ID` and `TIMESTAMP` headers when we add `SAVED` and `CREATED_DATE` * Control "already saved" logic in the `JdbcMessageStore`s via `DuplicateKeyException` on the `INSERT`. This is much effective then additional `SELECT` in case of `SAVED` before * Control "already saved" logic in the `AbstractConfigurableMongoDbMessageStore` via `DuplicateKeyException` on the `INSERT`. Since `MongoDbMessageStore` doesn't provide extra `messageId` field, perform extra `SELECT` before store document. Anyway the `MongoDbMessageStore` isn't recommended for use. We may consider to deprecate it * Control "already saved" logic in the `AbstractKeyValueMessageStore` via `putIfAbsent` operation With this fix we persist message in the store as is without any modifications when we perform standard serialization procedure. Any custom serializers should consider to use `MutableMessageBuilder` if there is a requirement to retain `ID` and `TIMESTAMP` Rework `MongoDbMetadataStore.putIfAbsent()` to normal `findAndModify()` with particular `$setOnInsert`. Technically the MongoDB query looks like: ``` db.collection.findAndModify({ query: { _id: $key }, update: { $setOnInsert: { value: $value } // perform modification only on upsert }, new: false, // don't return new doc if one is upserted upsert: true // insert the document if it does not exist }) ``` Move single import to the appropriate JavaDoc Polishing after rebase DEBUG messages in `doStoreIfAbsent()` implementations * To keep track of the extra message information in the `MessageStore`, without `Message` modification, introduce `MessageMetadata` and `MessageHolder` * Add `MessageStore#getMessageMetadata()` * Modify MongoDb `MessageStore` to add extra `timestamp` for individual message * Fix `ConcurrentAggregatorTests` race condition. Since currently the default release strategy is `SimpleSequenceSizeReleaseStrategy` which is just based on the `MessageGroup` size, there is no guaranty which messages will complete the group in concurrent environment. The test is really based on the `SequenceAwareMessageGroup` logic to discard the message with the same `correlationId` Fix `@Copyright` format Move cast to `MessageHolder` after `Assert.isInstanceOf(MessageHolder.class, messageHolder)` Retain backward compatibility in the `AbstractKeyValueMessageStore` Polishing
This commit is contained in:
committed by
Gary Russell
parent
7c12288d2e
commit
a1f554c04d
@@ -17,7 +17,6 @@
|
||||
package org.springframework.integration.redis.store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.BoundValueOperations;
|
||||
@@ -72,12 +71,34 @@ public class RedisMessageStore extends AbstractKeyValueMessageStore {
|
||||
ops.set(objectToStore);
|
||||
}
|
||||
catch (SerializationException e) {
|
||||
throw new IllegalArgumentException("If relying on the default RedisSerializer (JdkSerializationRedisSerializer) " +
|
||||
"the Object must be Serializable. Either make it Serializable or provide your own implementation of " +
|
||||
"RedisSerializer via 'setValueSerializer(..)'", e);
|
||||
rethrowAsIllegalArgumentException(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStoreIfAbsent(Object id, Object objectToStore) {
|
||||
Assert.notNull(id, "'id' must not be null");
|
||||
Assert.notNull(objectToStore, "'objectToStore' must not be null");
|
||||
BoundValueOperations<Object, Object> ops = this.redisTemplate.boundValueOps(id);
|
||||
try {
|
||||
Boolean present = ops.setIfAbsent(objectToStore);
|
||||
if (present != null && logger.isDebugEnabled()) {
|
||||
logger.debug("The message: [" + present + "] is already present in the store. " +
|
||||
"The [" + objectToStore + "] is ignored.");
|
||||
}
|
||||
}
|
||||
catch (SerializationException e) {
|
||||
rethrowAsIllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void rethrowAsIllegalArgumentException(SerializationException e) {
|
||||
throw new IllegalArgumentException("If relying on the default RedisSerializer " +
|
||||
"(JdkSerializationRedisSerializer) the Object must be Serializable. " +
|
||||
"Either make it Serializable or provide your own implementation of " +
|
||||
"RedisSerializer via 'setValueSerializer(..)'", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doRemove(Object id) {
|
||||
@@ -93,7 +114,6 @@ public class RedisMessageStore extends AbstractKeyValueMessageStore {
|
||||
@Override
|
||||
protected Collection<?> doListKeys(String keyPattern) {
|
||||
Assert.hasText(keyPattern, "'keyPattern' must not be empty");
|
||||
Set<Object> keys = this.redisTemplate.keys(keyPattern);
|
||||
return keys;
|
||||
return this.redisTemplate.keys(keyPattern);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user