INT-2334 Fix for MongoDbMessageStore storing MessageHistory
This fix ensures that MongoDbMessageStore properly stores MessageHistory that is stored in the 'history' header of MessageHeaders. polished contribution from Sean Brandt, added tests fixed header deserialization logic to ensure that objects are converted to a proper type removed write converter
This commit is contained in:
@@ -21,6 +21,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.store.AbstractMessageGroupStore;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
@@ -51,9 +53,14 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
import static org.springframework.integration.history.MessageHistory.NAME_PROPERTY;
|
||||
import static org.springframework.integration.history.MessageHistory.TIMESTAMP_PROPERTY;
|
||||
import static org.springframework.integration.history.MessageHistory.TYPE_PROPERTY;
|
||||
|
||||
/**
|
||||
* An implementation of both the {@link MessageStore} and {@link MessageGroupStore}
|
||||
@@ -61,6 +68,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Sean Brandt
|
||||
* @since 2.1
|
||||
*/
|
||||
public class MongoDbMessageStore extends AbstractMessageGroupStore implements MessageStore, BeanClassLoaderAware {
|
||||
@@ -298,6 +306,7 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore implements Me
|
||||
List<Converter<?, ?>> customConverters = new ArrayList<Converter<?,?>>();
|
||||
customConverters.add(new UuidToStringConverter());
|
||||
customConverters.add(new StringToUuidConverter());
|
||||
customConverters.add(new MessageHistoryToDBObjectConverter());
|
||||
this.setCustomConversions(new CustomConversions(customConverters));
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
@@ -344,7 +353,8 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore implements Me
|
||||
return super.read(clazz, source);
|
||||
}
|
||||
if (source != null) {
|
||||
Map<String, Object> headers = (Map<String, Object>) source.get("headers");
|
||||
Map<String, Object> headers = this.normalizeHeaders((Map<String, Object>) source.get("headers"));
|
||||
|
||||
Object payload = source.get("payload");
|
||||
Object payloadType = source.get(PAYLOAD_TYPE_KEY);
|
||||
if (payloadType != null && payload instanceof DBObject) {
|
||||
@@ -356,7 +366,7 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore implements Me
|
||||
throw new IllegalStateException("failed to load class: " + payloadType, e);
|
||||
}
|
||||
}
|
||||
GenericMessage message = new GenericMessage(payload, headers);
|
||||
GenericMessage message = new GenericMessage(payload, headers);
|
||||
Map innerMap = (Map) new DirectFieldAccessor(message.getHeaders()).getPropertyValue("headers");
|
||||
// using reflection to set ID and TIMESTAMP since they are immutable through MessageHeaders
|
||||
innerMap.put(MessageHeaders.ID, UUID.fromString((String) headers.get(MessageHeaders.ID)));
|
||||
@@ -389,7 +399,31 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore implements Me
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> normalizeHeaders(Map<String, Object> headers){
|
||||
Map<String, Object> newHeaders= new HashMap<String, Object>();
|
||||
for (String headerName : headers.keySet()) {
|
||||
Object headerValue = headers.get(headerName);
|
||||
if (headerValue instanceof DBObject){
|
||||
DBObject source = (DBObject) headerValue;
|
||||
Object type = source.get("_class");
|
||||
if (type != null){
|
||||
try {
|
||||
Class<?> typeClass = ClassUtils.forName(type.toString(), classLoader);
|
||||
Object obj = super.read(typeClass, source);
|
||||
newHeaders.put(headerName, obj);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Header '" + headerName + "' could not be deserialized due to exception: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
newHeaders.put(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
return newHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class UuidToStringConverter implements Converter<UUID, String> {
|
||||
@@ -405,6 +439,23 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore implements Me
|
||||
}
|
||||
}
|
||||
|
||||
private static class MessageHistoryToDBObjectConverter implements Converter<MessageHistory,DBObject> {
|
||||
|
||||
public DBObject convert(MessageHistory source) {
|
||||
BasicDBObject obj = new BasicDBObject();
|
||||
obj.put("_class", MessageHistory.class.getName());
|
||||
BasicDBList dbList = new BasicDBList();
|
||||
obj.put("components", dbList);
|
||||
for (Properties properties : source) {
|
||||
BasicDBObject dbo = new BasicDBObject();
|
||||
dbo.put(NAME_PROPERTY, properties.getProperty(NAME_PROPERTY));
|
||||
dbo.put(TYPE_PROPERTY, properties.getProperty(TYPE_PROPERTY));
|
||||
dbo.put(TIMESTAMP_PROPERTY, properties.getProperty(TIMESTAMP_PROPERTY));
|
||||
dbList.add(dbo);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper class used for storing Messages in MongoDB along with their "group" metadata.
|
||||
|
||||
Reference in New Issue
Block a user