diff --git a/build.gradle b/build.gradle
index b96f3d642a..f3dedf0f3e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -123,6 +123,8 @@ configure(javaprojects) {
mockitoVersion = '1.8.4'
springVersion = '3.1.0.M2'
springAmqpVersion = '1.0.0.RC2'
+ springDataMongoVersion = '1.0.0.BUILD-SNAPSHOT'
+ springDataCommonsVersion = '1.2.0.BUILD-SNAPSHOT'
springSecurityVersion = '3.0.5.RELEASE'
springWsVersion = '2.0.2.RELEASE'
@@ -321,6 +323,16 @@ project('spring-integration-mail') {
[compileJava,compileTestJava]*.options*.compilerArgs = ["${xLintArg},-path"]
}
+project('spring-integration-mongodb') {
+ description = 'Spring Integration MongoDB Support'
+ dependencies {
+ compile project(":spring-integration-core")
+ compile "org.springframework:spring-context:$springVersion"
+ compile "org.springframework.data:spring-data-mongodb:$springDataMongoVersion"
+ compile "org.springframework.data:spring-data-commons-core:$springDataCommonsVersion"
+ }
+}
+
project('spring-integration-rmi') {
description = 'Spring Integration RMI Support'
dependencies {
diff --git a/pom.xml b/pom.xml
index d01ae7a0a8..5b6833e553 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,6 +8,7 @@
pom
Spring Integration
+ spring-integration-amqp
spring-integration-core
spring-integration-event
spring-integration-feed
@@ -20,6 +21,7 @@
spring-integration-jms
spring-integration-jmx
spring-integration-mail
+ spring-integration-mongodb
spring-integration-rmi
spring-integration-security
spring-integration-sftp
diff --git a/settings.gradle b/settings.gradle
index b45d2f2a24..8138a6daab 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -30,6 +30,7 @@ include 'spring-integration-jdbc'
include 'spring-integration-jms'
include 'spring-integration-jmx'
include 'spring-integration-mail'
+include 'spring-integration-mongodb'
include 'spring-integration-rmi'
include 'spring-integration-security'
include 'spring-integration-sftp'
diff --git a/spring-integration-mongodb/pom.xml b/spring-integration-mongodb/pom.xml
new file mode 100644
index 0000000000..f4dd74208a
--- /dev/null
+++ b/spring-integration-mongodb/pom.xml
@@ -0,0 +1,173 @@
+
+
+ 4.0.0
+ org.springframework.integration
+ spring-integration-mongodb
+ 2.1.0.BUILD-SNAPSHOT
+ Spring Integration MongoDB Support
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+
+ src/main/java
+
+ **/*
+
+
+ **/*.java
+
+
+
+ src/main/resources
+
+ **/*
+
+
+
+
+
+ src/test/java
+
+ **/*
+
+
+ **/*.java
+
+
+
+ src/test/resources
+
+ **/*
+
+
+
+
+
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+ maven-surefire-plugin
+
+
+ **/*Tests.java
+
+
+ **/*Abstract*.java
+
+
+
+
+
+
+
+ http://download.java.net/maven/2
+ http://download.java.net/maven/2
+
+
+ http://maven.springframework.org/milestone
+ http://maven.springframework.org/milestone
+
+
+ http://maven.springframework.org/release
+ http://maven.springframework.org/release
+
+
+ http://maven.springframework.org/snapshot
+ http://maven.springframework.org/snapshot
+
+
+ http://repository.springsource.com/maven/bundles/external
+ http://repository.springsource.com/maven/bundles/external
+
+
+ http://repository.springsource.com/maven/bundles/milestone
+ http://repository.springsource.com/maven/bundles/milestone
+
+
+ http://repository.springsource.com/maven/bundles/release
+ http://repository.springsource.com/maven/bundles/release
+
+
+
+
+ org.easymock
+ easymock
+ 2.3
+ test
+
+
+ org.easymock
+ easymockclassextension
+ 2.3
+ test
+
+
+ org.springframework
+ spring-test
+ 3.1.0.M2
+ test
+
+
+ org.springframework.data
+ spring-data-mongodb
+ 1.0.0.BUILD-SNAPSHOT
+ compile
+
+
+ org.springframework.integration
+ spring-integration-core
+ 2.1.0.BUILD-SNAPSHOT
+ compile
+
+
+ org.springframework
+ spring-context
+ 3.1.0.M2
+ compile
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.1
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.8.4
+ test
+
+
+ log4j
+ log4j
+ 1.2.12
+ test
+
+
+ cglib
+ cglib-nodep
+ 2.2
+ test
+
+
+ junit
+ junit-dep
+ 4.8.2
+ test
+
+
+
+ UTF8
+
+
diff --git a/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoMessageStore.java b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoMessageStore.java
new file mode 100644
index 0000000000..952f6b3472
--- /dev/null
+++ b/spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/MongoMessageStore.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.mongodb.store;
+
+import static org.springframework.data.mongodb.core.query.Criteria.where;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.DirectFieldAccessor;
+import org.springframework.beans.factory.BeanClassLoaderAware;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.mapping.context.MappingContext;
+import org.springframework.data.mongodb.MongoDbFactory;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
+import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.convert.MongoConverter;
+import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
+import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.integration.Message;
+import org.springframework.integration.MessageHeaders;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.store.MessageStore;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+import com.mongodb.DBObject;
+import com.mongodb.Mongo;
+
+/**
+ * @author Mark Fisher
+ * @author Oleg Zhurakousky
+ */
+public class MongoMessageStore implements MessageStore, BeanClassLoaderAware {
+
+ private final static String DEFAULT_COLLECTION_NAME = "messages";
+
+ private final MongoTemplate template;
+
+ //private final MongoConverter mongoConverter = new MessageReadingMongoConverter();
+ private final MongoConverter mongoConverter = null;
+
+ private volatile ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
+
+
+ public MongoMessageStore(Mongo mongo, String databaseName) {
+ Assert.notNull(mongo, "mongo must not be null");
+ Assert.hasText(databaseName, "databaseName must not be empty");
+ MongoDbFactory mongoFactory = new SimpleMongoDbFactory(mongo, databaseName);
+ MessageReadingMongoConverter converter = new MessageReadingMongoConverter(mongoFactory, new MongoMappingContext());
+ this.template = new MongoTemplate(mongoFactory, converter);
+// this.template.setDefaultCollectionName(DEFAULT_COLLECTION_NAME);
+// this.template.createCollection(DEFAULT_COLLECTION_NAME);
+ }
+
+
+ public void setCollectionName(String collectionName) {
+ Assert.hasText(collectionName, "collectionName must not be empty");
+ //this.template.setDefaultCollectionName(collectionName);
+ this.template.createCollection(collectionName);
+ }
+
+// public void setUsername(String username) {
+// template.setUsername(username);
+// }
+//
+// public void setPassword(String password) {
+// template.setPassword(password);
+// }
+
+ public void setBeanClassLoader(ClassLoader classLoader) {
+ Assert.notNull(classLoader, "classLoader must not be null");
+ this.classLoader = classLoader;
+ }
+
+ public Message addMessage(Message message) {
+ this.template.insert(message, "messages");
+ return message;
+ }
+
+ public Message> getMessage(UUID id) {
+ return this.template.findOne(this.idQuery(id), Message.class);
+ }
+
+ public int getMessageCount() {
+ // TODO: long to int
+ return new Long(this.template.getCollection(DEFAULT_COLLECTION_NAME).getCount()).intValue();
+ }
+
+ public Message> removeMessage(UUID id) {
+ return this.template.findAndRemove(idQuery(id), Message.class, "messages");
+ }
+
+ private Query idQuery(UUID id) {
+ System.out.println(id.toString());
+ return new Query(where("_id").is(id.toString()));
+ }
+
+
+ private class MessageReadingMongoConverter extends MappingMongoConverter {
+
+ public MessageReadingMongoConverter(
+ MongoDbFactory mongoDbFactory,
+ MappingContext extends MongoPersistentEntity>, MongoPersistentProperty> mappingContext) {
+ super(mongoDbFactory, mappingContext);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ @Override
+ public void afterPropertiesSet() {
+ super.afterPropertiesSet();
+ Set> customConverters = new HashSet>();
+ customConverters.add(new UuidToStringConverter());
+ customConverters.add(new StringToUuidConverter());
+ //this.setCustomConverters(customConverters);
+ }
+
+
+ @Override
+ public void write(Object source, DBObject target) {
+ if (source instanceof Message) {
+ String payloadType = ((Message>) source).getPayload().getClass().getName();
+ target.put("_payloadType", payloadType);
+ target.put("_id", ((Message>) source).getHeaders().getId().toString());
+ }
+
+// // TODO: fix this (the base class should handle it via converters?)
+// if (source instanceof UUID) {
+// target.put("uuid", ((UUID)source).toString());
+// }
+ super.write(source, target);
+ }
+
+
+ @Override
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public S read(Class clazz, DBObject source) {
+ if (!Message.class.equals(clazz)) {
+ return super.read(clazz, source);
+ }
+ Map headers = (Map) source.get("headers");
+ Object payload = source.get("payload");
+ Object payloadType = source.get("_payloadType");
+ if (payloadType != null && payload instanceof DBObject) {
+ try {
+ Class> payloadClass = ClassUtils.forName(payloadType.toString(), classLoader);
+ payload = this.read(payloadClass, (DBObject) payload);
+ }
+ catch (Exception e) {
+ throw new IllegalStateException("failed to load class: " + payloadType, e);
+ }
+ }
+ GenericMessage message = new GenericMessage(payload, headers);
+ Map innerMap = (Map) new DirectFieldAccessor(message.getHeaders()).getPropertyValue("headers");
+ // TODO: unpick this mess
+ innerMap.put(MessageHeaders.ID, UUID.fromString(source.get("_id").toString()));
+ innerMap.put(MessageHeaders.TIMESTAMP, headers.get(MessageHeaders.TIMESTAMP));
+ return (S) message;
+ }
+ }
+
+
+ private static class UuidToStringConverter implements Converter {
+ public String convert(UUID source) {
+ return source.toString();
+ }
+ }
+
+
+ private static class StringToUuidConverter implements Converter {
+ public UUID convert(String source) {
+ return UUID.fromString(source);
+ }
+ }
+
+}
diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoClaimCheckIntegrationTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoClaimCheckIntegrationTests.java
new file mode 100644
index 0000000000..1cc6e74bf2
--- /dev/null
+++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoClaimCheckIntegrationTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.mongodb.store;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.springframework.integration.Message;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.integration.transformer.ClaimCheckInTransformer;
+import org.springframework.integration.transformer.ClaimCheckOutTransformer;
+
+import com.mongodb.Mongo;
+
+/**
+ * @author Mark Fisher
+ */
+public class MongoClaimCheckIntegrationTests {
+
+ @Test @Ignore
+ public void stringPayload() throws Exception {
+ Mongo mongo = new Mongo();
+ MongoMessageStore messageStore = new MongoMessageStore(mongo, "test");
+ ClaimCheckInTransformer checkin = new ClaimCheckInTransformer(messageStore);
+ ClaimCheckOutTransformer checkout = new ClaimCheckOutTransformer(messageStore);
+ Message> originalMessage = MessageBuilder.withPayload("test1").build();
+ Message> claimCheckMessage = checkin.transform(originalMessage);
+ assertEquals(originalMessage.getHeaders().getId(), claimCheckMessage.getPayload());
+ Message> checkedOutMessage = checkout.transform(claimCheckMessage);
+ assertEquals(claimCheckMessage.getPayload(), checkedOutMessage.getHeaders().getId());
+ assertEquals(originalMessage.getPayload(), checkedOutMessage.getPayload());
+ assertEquals(originalMessage, checkedOutMessage);
+ //System.out.println("original: " + originalMessage);
+ //System.out.println("claimcheck: " + claimCheckMessage);
+ //System.out.println("checkedout: " + checkedOutMessage);
+ }
+
+ @Test @Ignore
+ public void objectPayload() throws Exception {
+ Mongo mongo = new Mongo();
+ MongoMessageStore messageStore = new MongoMessageStore(mongo, "test");
+ ClaimCheckInTransformer checkin = new ClaimCheckInTransformer(messageStore);
+ ClaimCheckOutTransformer checkout = new ClaimCheckOutTransformer(messageStore);
+ Beverage payload = new Beverage();
+ payload.setName("latte");
+ payload.setShots(3);
+ payload.setIced(false);
+ Message> originalMessage = MessageBuilder.withPayload(payload).build();
+ Message> claimCheckMessage = checkin.transform(originalMessage);
+ assertEquals(originalMessage.getHeaders().getId(), claimCheckMessage.getPayload());
+ Message> checkedOutMessage = checkout.transform(claimCheckMessage);
+ assertEquals(originalMessage.getPayload(), checkedOutMessage.getPayload());
+ assertEquals(claimCheckMessage.getPayload(), checkedOutMessage.getHeaders().getId());
+ assertEquals(originalMessage, checkedOutMessage);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static class Beverage {
+
+ private String name;
+ private int shots;
+ private boolean iced;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getShots() {
+ return shots;
+ }
+
+ public void setShots(int shots) {
+ this.shots = shots;
+ }
+
+ public boolean isIced() {
+ return iced;
+ }
+
+ public void setIced(boolean iced) {
+ this.iced = iced;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (iced ? 1231 : 1237);
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + shots;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Beverage other = (Beverage) obj;
+ if (iced != other.iced) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ }
+ else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (shots != other.shots) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+}
diff --git a/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoMessageStoreTests.java b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoMessageStoreTests.java
new file mode 100644
index 0000000000..5c434075c4
--- /dev/null
+++ b/spring-integration-mongodb/src/test/java/org/springframework/integration/mongodb/store/MongoMessageStoreTests.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.integration.mongodb.store;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.springframework.integration.Message;
+import org.springframework.integration.support.MessageBuilder;
+
+import com.mongodb.Mongo;
+
+/**
+ * @author Mark Fisher
+ */
+public class MongoMessageStoreTests {
+
+ @Test @Ignore
+ public void addAndRemove() throws Exception {
+ Mongo mongo = new Mongo();
+ MongoMessageStore store = new MongoMessageStore(mongo, "test");
+ Message> message = MessageBuilder.withPayload("UUID again and again").build();
+ Message> claimCheck = store.addMessage(message);
+ System.out.println("added: " + claimCheck);
+ //Thread.sleep(10000);
+ message = store.removeMessage(message.getHeaders().getId());
+ System.out.println("removed: " + message);
+ }
+
+}
diff --git a/spring-integration-mongodb/template.mf b/spring-integration-mongodb/template.mf
new file mode 100644
index 0000000000..a40a9053e4
--- /dev/null
+++ b/spring-integration-mongodb/template.mf
@@ -0,0 +1,17 @@
+Bundle-SymbolicName: org.springframework.integration.mongodb
+Bundle-Name: Spring Integration MongoDB Support
+Bundle-Vendor: SpringSource
+Bundle-ManifestVersion: 2
+Import-Template:
+ org.apache.commons.logging;version="[1.1.1, 2.0.0)",
+ org.springframework.integration.*;version="[2.0.0, 2.0.1)",
+ org.springframework.beans.*;version="[3.0.0, 4.0.0)",
+ org.springframework.context;version="[3.0.0, 4.0.0)",
+ org.springframework.core.*;version="[3.0.0, 4.0.0)",
+ org.springframework.expression.*;version="[3.0.0, 4.0.0)",
+ org.springframework.util;version="[3.0.0, 4.0.0)",
+ org.springframework.expression.*;version="[3.0.0, 4.0.0)",
+ org.springframework.data.document.mongodb.*;version="[1.0.0, 2.0.0)",
+ com.mongodb.*;version="[2.4.0, 2.5.0]",
+ javax.*;version="0",
+ org.w3c.dom.*;version="0"