GH-2936: Add custom converters for MongoDbMS
Fixes https://github.com/spring-projects/spring-integration/issues/2936 * Add `MongoDbMessageStore.setCustomConverters()` to allow to inject any custom converters for `payload` as well as header values **Cherry-pick to 5.1.x**
This commit is contained in:
committed by
Gary Russell
parent
f992c05736
commit
ef856b2187
@@ -17,7 +17,9 @@
|
||||
package org.springframework.integration.mongodb.store;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -140,13 +142,12 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
|
||||
private final String collectionName;
|
||||
|
||||
private volatile ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
private ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private String[] whiteListPatterns;
|
||||
|
||||
|
||||
/**
|
||||
* Create a MongoDbMessageStore using the provided {@link MongoDbFactory}.and the default collection name.
|
||||
* @param mongoDbFactory The mongodb factory.
|
||||
@@ -186,7 +187,20 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
* @param patterns the patterns.
|
||||
*/
|
||||
public void addWhiteListPatterns(String... patterns) {
|
||||
this.whiteListPatterns = patterns;
|
||||
this.whiteListPatterns = patterns != null ? Arrays.copyOf(patterns, patterns.length) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a set of converters to use in the {@link MappingMongoConverter}.
|
||||
* Must be instances of {@code org.springframework.core.convert.converter.Converter},
|
||||
* {@code org.springframework.core.convert.converter.ConverterFactory},
|
||||
* {@code org.springframework.core.convert.converter.GenericConverter} or
|
||||
* {@code org.springframework.data.convert.ConverterBuilder.ConverterAware}.
|
||||
* @param customConverters the converters to use.
|
||||
* @since 5.1.6
|
||||
*/
|
||||
public void setCustomConverters(Object... customConverters) {
|
||||
this.converter.setCustomConverters(customConverters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -194,6 +208,7 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
if (this.applicationContext != null) {
|
||||
this.converter.setApplicationContext(this.applicationContext);
|
||||
}
|
||||
|
||||
this.converter.afterPropertiesSet();
|
||||
|
||||
IndexOperations indexOperations = this.template.indexOps(this.collectionName);
|
||||
@@ -512,26 +527,38 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
|
||||
*/
|
||||
private final class MessageReadingMongoConverter extends MappingMongoConverter {
|
||||
|
||||
private Object[] customConverters;
|
||||
|
||||
MessageReadingMongoConverter(MongoDbFactory mongoDbFactory,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
super(new DefaultDbRefResolver(mongoDbFactory), mappingContext);
|
||||
}
|
||||
|
||||
void setCustomConverters(Object... customConverters) {
|
||||
this.customConverters =
|
||||
customConverters != null ? Arrays.copyOf(customConverters, customConverters.length) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
List<Object> customConverters = new ArrayList<>();
|
||||
customConverters.add(new MessageHistoryToDocumentConverter());
|
||||
customConverters.add(new DocumentToGenericMessageConverter());
|
||||
customConverters.add(new DocumentToMutableMessageConverter());
|
||||
List<Object> converters = new ArrayList<>();
|
||||
converters.add(new MessageHistoryToDocumentConverter());
|
||||
converters.add(new DocumentToGenericMessageConverter());
|
||||
converters.add(new DocumentToMutableMessageConverter());
|
||||
DocumentToErrorMessageConverter docToErrorMessageConverter = new DocumentToErrorMessageConverter();
|
||||
if (MongoDbMessageStore.this.whiteListPatterns != null) {
|
||||
docToErrorMessageConverter.deserializingConverter
|
||||
.addWhiteListPatterns(MongoDbMessageStore.this.whiteListPatterns);
|
||||
}
|
||||
customConverters.add(docToErrorMessageConverter);
|
||||
customConverters.add(new DocumentToAdviceMessageConverter());
|
||||
customConverters.add(new ThrowableToBytesConverter());
|
||||
this.setCustomConversions(new MongoCustomConversions(customConverters));
|
||||
converters.add(docToErrorMessageConverter);
|
||||
converters.add(new DocumentToAdviceMessageConverter());
|
||||
converters.add(new ThrowableToBytesConverter());
|
||||
|
||||
if (this.customConverters != null) {
|
||||
Collections.addAll(converters, this.customConverters);
|
||||
}
|
||||
|
||||
setCustomConversions(new MongoCustomConversions(converters));
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,18 @@
|
||||
|
||||
package org.springframework.integration.mongodb.store;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
@@ -36,4 +46,49 @@ public class MongoDbMessageStoreTests extends AbstractMongoDbMessageStoreTests {
|
||||
return mongoDbMessageStore;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomConverter() throws Exception {
|
||||
MongoDbMessageStore mongoDbMessageStore =
|
||||
new MongoDbMessageStore(new SimpleMongoDbFactory(new MongoClient(), "test"));
|
||||
FooToBytesConverter fooToBytesConverter = new FooToBytesConverter();
|
||||
mongoDbMessageStore.setCustomConverters(fooToBytesConverter);
|
||||
mongoDbMessageStore.afterPropertiesSet();
|
||||
|
||||
mongoDbMessageStore.addMessage(new GenericMessage<>(new Foo("foo")));
|
||||
|
||||
assertThat(fooToBytesConverter.called.await(10, TimeUnit.SECONDS)).isTrue();
|
||||
}
|
||||
|
||||
private static class Foo {
|
||||
|
||||
String foo;
|
||||
|
||||
Foo(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
private static class FooToBytesConverter implements Converter<Foo, byte[]> {
|
||||
|
||||
private final CountDownLatch called = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public byte[] convert(Foo source) {
|
||||
try {
|
||||
return source.toString().getBytes();
|
||||
}
|
||||
finally {
|
||||
this.called.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ The `MongoDbMessageStore` expands the `Message` as a Mongo document with all nes
|
||||
It is useful when you need to have access to the `payload` or `headers` for auditing or analytics -- for example, against stored messages.
|
||||
|
||||
IMPORTANT: The `MongoDbMessageStore` uses a custom `MappingMongoConverter` implementation to store `Message` instances as MongoDB documents, and there are some limitations for the properties (`payload` and `header` values) of the `Message`.
|
||||
For example, there is no ability to configure custom converters for complex domain `payload` instances or `header` values.
|
||||
There is also no way to provide a custom `MongoTemplate` (or `MappingMongoConverter`).
|
||||
To achieve these capabilities, an alternative MongoDB `MessageStore` implementation has been introduced (we describe it next).
|
||||
|
||||
Starting with version 5.1.6, the `MongoDbMessageStore` can be configured with custom converters which are propagated into an internal `MappingMongoConverter` implementation.
|
||||
See `MongoDbMessageStore.setCustomConverters(Object... customConverters)` JavaDocs for more information.
|
||||
|
||||
Spring Integration 3.0 introduced the `ConfigurableMongoDbMessageStore`.
|
||||
It implements both the `MessageStore` and `MessageGroupStore` interfaces.
|
||||
|
||||
Reference in New Issue
Block a user