From fb39f01f25c6144dab347b120265942113bde915 Mon Sep 17 00:00:00 2001 From: Mark Pollack Date: Tue, 24 May 2011 22:09:12 -0400 Subject: [PATCH] DATADOC-88 - Create MongoDbFactory to consolidate DB, Server location, and user credentials into one location DATADOC-147 - Update reference documentation to cover changes from M2 to M3 (partial work) --- .../mongodb/SimpleMongoDbFactory.java | 6 - .../mongodb/config/MongoDbFactoryParser.java | 49 ++---- .../mongodb/config/spring-mongo-1.0.xsd | 2 + .../mongodb/config/MongoNamespaceTests.java | 12 ++ .../config/MongoNamespaceTests-context.xml | 21 ++- src/docbkx/reference/mongodb.xml | 148 +++++++++++++++--- 6 files changed, 168 insertions(+), 70 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoDbFactory.java index e82d97c66..35f521a0a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoDbFactory.java @@ -56,11 +56,5 @@ public class SimpleMongoDbFactory implements MongoDbFactory { Assert.hasText(dbName, "Database name must not be empty"); return MongoDbUtils.getDB(mongo, dbName, username, password == null ? null : password.toCharArray()); } - - - - public Mongo getMongo() { - return this.mongo; - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoDbFactoryParser.java index f28eb6a15..dcdd7ccca 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoDbFactoryParser.java @@ -23,14 +23,12 @@ import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.authentication.UserCredentials; import org.springframework.data.document.mongodb.MongoFactoryBean; import org.springframework.data.document.mongodb.SimpleMongoDbFactory; import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** @@ -49,7 +47,6 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { - BeanDefinitionRegistry registry = parserContext.getRegistry(); BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class); // UserCredentials @@ -83,46 +80,22 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { dbname = "db"; } - + // com.mongodb.Mongo object String mongoRef = element.getAttribute("mongo-ref"); - String mongoId = null; - if (!StringUtils.hasText(mongoRef)) { - BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class); - Element mongoEl = DomUtils.getChildElementByTagName(element, "mongo"); - if (null != mongoEl) { - String overrideHost = mongoEl.getAttribute("host"); - mongoBuilder.addPropertyValue("host", (StringUtils.hasText(overrideHost) ? overrideHost : host)); - String overridePort = mongoEl.getAttribute("port"); - mongoBuilder.addPropertyValue("port", (StringUtils.hasText(overridePort) ? overridePort : port)); - ParsingUtils.parseMongoOptions(parserContext, mongoEl, mongoBuilder); - ParsingUtils.parseReplicaSet(parserContext, mongoEl, mongoBuilder); - String innerId = mongoEl.getAttribute("id"); - if (StringUtils.hasText(innerId)) { - mongoId = innerId; - } - } - else { - mongoBuilder.addPropertyValue("host", host); - mongoBuilder.addPropertyValue("port", port); - } - - /* MLP - WIP - if (mongoId == null) { - mongoRef = BeanDefinitionReaderUtils.registerWithGeneratedName(mongoBuilder.getBeanDefinition(), parserContext.getRegistry()); - } else { - registry.registerBeanDefinition(MONGO, mongoBuilder.getBeanDefinition()); - mongoRef = MONGO; - } - */ - registry.registerBeanDefinition(MONGO, mongoBuilder.getBeanDefinition()); - mongoRef = MONGO; - } + if (!StringUtils.hasText(mongoRef)) { + //Create implicit com.mongodb.Mongo object and register under generated name + BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class); + mongoBuilder.addPropertyValue("host", host); + mongoBuilder.addPropertyValue("port", port); + mongoRef = BeanDefinitionReaderUtils.registerWithGeneratedName(mongoBuilder.getBeanDefinition(), parserContext.getRegistry()); + } dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef)); dbFactoryBuilder.addConstructorArgValue(dbname); dbFactoryBuilder.addConstructorArgValue(userCredentialsBuilder.getBeanDefinition()); return dbFactoryBuilder.getRawBeanDefinition(); - } - + + } + } diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd index 61ab9ff8d..e5d92d50e 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd @@ -39,6 +39,7 @@ Defines a MongoDbFactory for connecting to a specific database ]]> + - - + - - + + + + + + + @@ -46,5 +55,9 @@ + + + + diff --git a/src/docbkx/reference/mongodb.xml b/src/docbkx/reference/mongodb.xml index 638f39c1f..0e6742eb9 100644 --- a/src/docbkx/reference/mongodb.xml +++ b/src/docbkx/reference/mongodb.xml @@ -77,7 +77,7 @@ the base MongoDB Java driver so you can easily map your existing knowledge onto the Spring APIs. -
+
Getting Started Spring MongoDB support requires MongoDB 1.4 or higher and Java SE 5 @@ -470,17 +470,16 @@ public class AppConfig {
- Registering a MongoDbFactory instance using Java based - metadata + The MongoDbFactory interface - As an alternative to configuring a - com.mongodb.Mongo instance and later providing - the database name and optionally the username and password, is to use - SimpleMongoDbFactory, which implements the - MongoDbFactory inteface shown below. A - reference to MongoDbFactory can be passed - to constructors of MongoTemplate to simplify its - creation. + While com.mongodb.Mongo is the entry point to the MongoDB driver + API, connecting to a specific MongoDB database instance requires + additional information such as the database name and an optional + username and password. With that information you can obtain a + com.mongodb.DB object and access all the functionality of a specific + MongoDB database instance. Spring provides the + org.springframework.data.document.mongodb.MongoDbFactory + interface shown below to bootstrap connectivity to the database. public interface MongoDbFactory { @@ -490,9 +489,55 @@ public class AppConfig { } - The most simple usage is shown below + The following sections show how you can use the contiainer with + either Java or the XML based metadata to configure an instance of the + MongoDbFactory interface. In turn, you can use + the MongoDbFactory instance to configure + MongoTemplate. - @Configuration + The class + org.springframework.data.document.mongodb.SimpleMongoDbFactory + provides implements the MongoDbFactory interface and is created with a + standard com.mongodb.Mongo instance, the database + name and an optional + org.springframework.data.authentication.UserCredentials + constructor argument. + + Instead of using the IoC container to create an instance of + MongoTemplate, you can just use them in standard Java code as shown + below. + + public class MongoApp { + + private static final Log log = LogFactory.getLog(MongoApp.class); + + public static void main(String[] args) throws Exception { + + MongoOperations mongoOps = new MongoTemplate(new SimpleMongoDbFactory(new Mongo(), "database")); + + mongoOps.insert(new Person("Joe", 34)); + + log.info(mongoOps.findOne(new Query(where("name").is("Joe")), Person.class)); + + mongoOps.dropCollection("person"); + } +} + + The code in bold highlights the use of SimpleMongoDbFactory and is + the only difference between the listing shown in the getting started + section. +
+ +
+ Registering a MongoDbFactory instance using Java based + metadata + + To register a MongoDbFactory instance with the container, you + write code much like what was highlighted in the previous code listing. + A simple example is shown below + + @Configuration public class MongoConfiguration { public @Bean MongoDbFactory mongoDbFactory() throws Exception { @@ -502,29 +547,88 @@ public class MongoConfiguration { } To define the username and password create an instance of - org.springframework.data.authentication.UserCredentials and pass it into - the constructor as shown below + org.springframework.data.authentication.UserCredentials + and pass it into the constructor as shown below. This listing also shows + using MongoDbFactory register an instance of + MongoTemplate with the container. - @Configuration + @Configuration public class MongoConfiguration { public @Bean MongoDbFactory mongoDbFactory() throws Exception { UserCredentials userCredentials = new UserCredentials("joe", "secret"); return new SimpleMongoDbFactory(new Mongo(), "database", userCredentials); } + + public @Bean MongoTemplate mongoTemplate() throws Exception { + return new MongoTemplate(mongoDbFactory()); + } } + +
- Registering a Mongo instance using XML based metadata + Registering a MongoDbFactory instance using XML based + metadata - The mongo namespace lets you create a MongoDbFactory instance - which is a convenient way to group together the a mongo instance, a - database name and an optional username and password. A simple usage is - shown below + The mongo namespace provides a convient way to create a + SimpleMongoDbFactory as compared to using + the<beans/> namespace. Simple usage is shown + below - <mongo:db-factory dbname="database" > + <mongo:db-factory dbname="database"> + + In the above example a com.mongodb.Mongo + instance is created using the default host and port number. The + SimpleMongoDbFactory registered with the + container is identified by the id 'mongoDbFactory' unless a value for + the id attribute is specified. + + You can also provide the host and port for the underlying + com.mongodb.Mongo instance as shown below, in addition to username and + password for the database. + + <mongo:db-factory id="anotherMongoDbFactory" + host="localhost" + port="27017" + dbname="database" + username="joe" + password="secret"/> + + If you need to configure additional options on the + com.mongodb.Mongo instance that is used to create + a SimpleMongoDbFactory you can refer to an + existing bean using the mongo-ref attribute as shown + below. To show another common usage pattern, this listing show the use + of a property placeholder to parameterise the configuration and creating + MongoTemplate. + + <context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties"/> + +<mongo:mongo host="${mongo.host}" port="${mongo.port}"> + <mongo:options + connections-per-host="${mongo.connectionsPerHost}" + threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" + connect-timeout="${mongo.connectTimeout}" + max-wait-time="${mongo.maxWaitTime}" + auto-connect-retry="${mongo.autoConnectRetry}" + socket-keep-alive="${mongo.socketKeepAlive}" + socket-timeout="${mongo.socketTimeout}" + slave-ok="${mongo.slaveOk}" + write-number="1" + write-timeout="0" + write-fsync="true"/> +</mongo:mongo> + +<mongo:db-factory dbname="database" mongo-ref="mongo"/> + +<bean id="anotherMongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate"> + <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> +</bean> + +