diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java
index 8e57f0964..e8d0545e9 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 by the original author(s).
+ * Copyright 2011 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.data.mongodb.config;
import static org.springframework.data.mongodb.config.BeanNames.*;
+import static org.springframework.data.mongodb.config.ParsingUtils.*;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -33,6 +34,7 @@ import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import com.mongodb.Mongo;
+import com.mongodb.MongoURI;
/**
* {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s.
@@ -54,31 +56,37 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
-
+
+ String uri = element.getAttribute("uri");
String mongoRef = element.getAttribute("mongo-ref");
- if (!StringUtils.hasText(mongoRef)) {
- mongoRef = registerMongoBeanDefinition(element, parserContext);
- }
-
- // Database name
String dbname = element.getAttribute("dbname");
- if (!StringUtils.hasText(dbname)) {
- dbname = "db";
- }
+ BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
+ // Common setup
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
+ ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
+
+ if (StringUtils.hasText(uri)) {
+ if(StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
+ parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", parserContext.extractSource(element));
+ }
+
+ dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
+ return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
+ }
+
+ // Defaulting
+ mongoRef = StringUtils.hasText(mongoRef) ? mongoRef : registerMongoBeanDefinition(element, parserContext);
+ dbname = StringUtils.hasText(dbname) ? dbname : "db";
+
dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef));
dbFactoryBuilder.addConstructorArgValue(dbname);
- BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element);
if (userCredentials != null) {
dbFactoryBuilder.addConstructorArgValue(userCredentials);
}
- ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
-
- return dbFactoryBuilder.getBeanDefinition();
-
+ return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
}
/**
@@ -105,7 +113,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
* @param element
* @return the {@link BeanDefinition} or {@literal null} if neither username nor password given.
*/
- private BeanDefinition getUserCredentialsBeanDefinition(Element element) {
+ private BeanDefinition getUserCredentialsBeanDefinition(Element element, ParserContext context) {
String username = element.getAttribute("username");
String password = element.getAttribute("password");
@@ -118,6 +126,20 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(username) ? username : null);
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(password) ? password : null);
- return userCredentialsBuilder.getBeanDefinition();
+ return getSourceBeanDefinition(userCredentialsBuilder, context, element);
+ }
+
+ /**
+ * Creates a {@link BeanDefinition} for a {@link MongoURI}.
+ *
+ * @param uri
+ * @return
+ */
+ private BeanDefinition getMongoUri(String uri) {
+
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoURI.class);
+ builder.addConstructorArgValue(uri);
+
+ return builder.getBeanDefinition();
}
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ParsingUtils.java
index 2f646d74c..1f3ef877b 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ParsingUtils.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ParsingUtils.java
@@ -16,6 +16,8 @@
package org.springframework.data.mongodb.config;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
@@ -110,4 +112,19 @@ abstract class ParsingUtils {
builder.addPropertyValue(attrName, attr);
}
}
+
+ /**
+ * Returns the {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder} enriched with source
+ * information derived from the given {@link Element}.
+ *
+ * @param builder must not be {@literal null}.
+ * @param context must not be {@literal null}.
+ * @param element must not be {@literal null}.
+ * @return
+ */
+ static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, ParserContext context, Element element) {
+ AbstractBeanDefinition definition = builder.getBeanDefinition();
+ definition.setSource(context.extractSource(element));
+ return definition;
+ }
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java
index 978a787b2..4fc4856c1 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java
@@ -15,6 +15,8 @@
*/
package org.springframework.data.mongodb.core;
+import java.net.UnknownHostException;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
@@ -25,6 +27,8 @@ import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+import com.mongodb.MongoURI;
import com.mongodb.WriteConcern;
/**
@@ -69,6 +73,19 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
this.username = userCredentials.getUsername();
this.password = userCredentials.getPassword();
}
+
+ /**
+ * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoURI}.
+ *
+ * @param uri must not be {@literal null}.
+ * @throws MongoException
+ * @throws UnknownHostException
+ * @see MongoURI
+ */
+ public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException {
+
+ this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), String.valueOf(uri.getPassword())));
+ }
/**
* Configures the {@link WriteConcern} to be used on the {@link DB} instance being created.
diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
index 51b0b84a3..058066e01 100644
--- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
+++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
@@ -87,6 +87,12 @@ The password to use when connecting to a MongoDB server.
]]>
+
+
+
+
+
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java
index c5f629efe..52848a247 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java
@@ -23,10 +23,14 @@ import java.util.List;
import org.junit.Test;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import com.mongodb.Mongo;
+import com.mongodb.MongoURI;
/**
* Integration tests for {@link MongoDbFactoryParser}.
@@ -60,4 +64,27 @@ public class MongoDbFactoryParserIntegrationTests {
Mongo mongo = factory.getBean(Mongo.class);
assertThat(mongo.getMongoOptions().maxAutoConnectRetryTime, is(27L));
}
+
+ /**
+ * @see DATADOC-295
+ */
+ @Test
+ public void setsUpMongoDbFactoryUsingAMongoUri() {
+
+ XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("namespace/mongo-uri.xml"));
+ BeanDefinition definition = factory.getBeanDefinition("mongoDbFactory");
+ ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
+
+ assertThat(constructorArguments.getArgumentCount(), is(1));
+ ValueHolder argument = constructorArguments.getArgumentValue(0, MongoURI.class);
+ assertThat(argument, is(notNullValue()));
+ }
+
+ /**
+ * @see DATADOC-295
+ */
+ @Test(expected = BeanDefinitionParsingException.class)
+ public void rejectsUriPlusDetailedConfiguration() {
+ new XmlBeanFactory(new ClassPathResource("namespace/mongo-uri-and-details.xml"));
+ }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java
index 609f264b9..282f1076c 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java
@@ -16,12 +16,19 @@
package org.springframework.data.mongodb.core;
import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+import java.net.UnknownHostException;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.data.mongodb.MongoDbFactory;
+import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.Mongo;
+import com.mongodb.MongoURI;
/**
* Unit tests for {@link SimpleMongoDbFactory}.
@@ -53,6 +60,22 @@ public class SimpleMongoDbFactoryUnitTests {
new SimpleMongoDbFactory(mongo, "foo01231bar");
}
+ /**
+ * @see DATADOC-295
+ * @throws UnknownHostException
+ */
+ @Test
+ public void mongoUriConstructor() throws UnknownHostException {
+
+ MongoURI mongoURI = new MongoURI("mongodb://myUsername:myPassword@localhost/myDatabase.myCollection");
+ MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoURI);
+
+ assertThat(ReflectionTestUtils.getField(mongoDbFactory, "username").toString(), is("myUsername"));
+ assertThat(ReflectionTestUtils.getField(mongoDbFactory, "password").toString(), is("myPassword"));
+ assertThat(ReflectionTestUtils.getField(mongoDbFactory, "databaseName").toString(), is("myDatabase"));
+ assertThat(ReflectionTestUtils.getField(mongoDbFactory, "databaseName").toString(), is("myDatabase"));
+ }
+
private void rejectsDatabaseName(String databaseName) {
try {
diff --git a/spring-data-mongodb/src/test/resources/namespace/mongo-uri-and-details.xml b/spring-data-mongodb/src/test/resources/namespace/mongo-uri-and-details.xml
new file mode 100644
index 000000000..7239228e3
--- /dev/null
+++ b/spring-data-mongodb/src/test/resources/namespace/mongo-uri-and-details.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/spring-data-mongodb/src/test/resources/namespace/mongo-uri.xml b/spring-data-mongodb/src/test/resources/namespace/mongo-uri.xml
new file mode 100644
index 000000000..51175ecba
--- /dev/null
+++ b/spring-data-mongodb/src/test/resources/namespace/mongo-uri.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+