DATADOC-88 - Create MongoDbFactory to consolidate DB, Server location, and user credentials into one location

This commit is contained in:
Mark Pollack
2011-05-24 17:17:54 -04:00
parent 46e2cf698e
commit 2284a5137e
9 changed files with 128 additions and 221 deletions

View File

@@ -25,7 +25,7 @@
<property name="port" value="27017"/> <property name="port" value="27017"/>
</bean> </bean>
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean"> <bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.SimpleMongoDbFactory">
<constructor-arg name="mongo" ref="mongo"/> <constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/> <constructor-arg name="databaseName" value="database"/>
</bean> </bean>

View File

@@ -11,6 +11,4 @@ public interface MongoDbFactory {
Mongo getMongo(); Mongo getMongo();
String getDatabaseName();
} }

View File

@@ -1,154 +0,0 @@
/*
* Copyright 2010-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.data.document.mongodb;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
* Convenient factory for configuring MongoDB.
*
* @author Thomas Risberg
* @since 1.0
*/
public class MongoDbFactoryBean implements MongoDbFactory, FactoryBean<MongoDbFactory>, InitializingBean {
//ToDo: add PersistenceExceptionTranslator ???
/**
* Logger, available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo;
private String host;
private Integer port;
private String databaseName;
private String username;
private String password;
public MongoDbFactoryBean() {
}
public MongoDbFactoryBean(Mongo mongo, String databaseName, UserCredentials userCredentials) throws DataAccessException {
this(mongo, databaseName);
this.username = userCredentials.getUsername();
this.password = userCredentials.getPassword();
}
public MongoDbFactoryBean(Mongo mongo, String databaseName) throws DataAccessException {
Assert.notNull(mongo, "Mongo must not be null");
Assert.hasText(databaseName, "Database name must not be empty");
this.mongo = mongo;
this.databaseName = databaseName;
try {
afterPropertiesSet();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException)e;
}
else {
throw new DataAccessResourceFailureException("Error while initializing DB Factory", e);
}
}
}
public void setMongo(Mongo mongo) {
this.mongo = mongo;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public void setHost(String host) {
this.host = host;
}
public void setPort(int port) {
this.port = port;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public DB getDb() throws DataAccessException {
Assert.notNull(mongo, "Mongo must not be null");
Assert.hasText(databaseName, "Database name must not be empty");
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
public Mongo getMongo() {
return this.mongo;
}
public String getDatabaseName() {
return this.databaseName;
}
public MongoDbFactory getObject() throws Exception {
return this;
}
public Class<? extends MongoDbFactory> getObjectType() {
return MongoDbFactory.class;
}
public boolean isSingleton() {
return false;
}
public void afterPropertiesSet() throws Exception {
// apply defaults - convenient when used to configure for tests
// in an application context
//ToDo: do we need a default or should we require database name?
// if (databaseName == null) {
// logger.warn("Property databaseName not specified. Using default name 'test'");
// databaseName = "test";
// }
if (mongo == null) {
logger.warn("Property mongo not specified. Using default configuration");
if (host == null) {
mongo = new Mongo();
}
else {
if (port == null) {
mongo = new Mongo(host);
}
else {
mongo = new Mongo(host, port);
}
}
}
}
}

View File

@@ -122,7 +122,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* @param databaseName * @param databaseName
*/ */
public MongoTemplate(Mongo mongo, String databaseName) { public MongoTemplate(Mongo mongo, String databaseName) {
this(new MongoDbFactoryBean(mongo, databaseName), null, null, null); this(new SimpleMongoDbFactory(mongo, databaseName), null, null, null);
} }
/** /**
@@ -134,7 +134,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
* @param userCredentials * @param userCredentials
*/ */
public MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials) { public MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials) {
this(new MongoDbFactoryBean(mongo, databaseName, userCredentials)); this(new SimpleMongoDbFactory(mongo, databaseName, userCredentials));
} }
/** /**

View File

@@ -0,0 +1,58 @@
package org.springframework.data.document.mongodb;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
public class SimpleMongoDbFactory implements MongoDbFactory {
/**
* Logger, available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo;
private String databaseName;
private String username;
private String password;
/**
* Create an instance of SimpleMongoDbFactory given the Mongo instance and database name
* @param mongo Mongo instance, not null
* @param databaseName Database name, not null
*/
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
Assert.notNull(mongo, "Mongo must not be null");
Assert.hasText(databaseName, "Database name must not be empty");
this.mongo = mongo;
this.databaseName = databaseName;
}
/**
* Create an instance of SimpleMongoDbFactory given the Mongo instance, database name, and username/password
* @param mongo Mongo instance, not null
* @param databaseName Database name, not null
* @param userCredentials username and password
*/
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials userCredentials) {
this(mongo, databaseName);
this.username = userCredentials.getUsername();
this.password = userCredentials.getPassword();
}
public DB getDb() throws DataAccessException {
Assert.notNull(mongo, "Mongo must not be null");
Assert.hasText(databaseName, "Database name must not be empty");
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
public Mongo getMongo() {
return this.mongo;
}
}

View File

@@ -26,8 +26,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent; import org.springframework.data.annotation.Persistent;
import org.springframework.data.document.mongodb.MongoDbFactory; import org.springframework.data.document.mongodb.MongoDbFactory;
import org.springframework.data.document.mongodb.MongoDbFactoryBean;
import org.springframework.data.document.mongodb.MongoTemplate; import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.SimpleMongoDbFactory;
import org.springframework.data.document.mongodb.convert.MappingMongoConverter; import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
import org.springframework.data.document.mongodb.mapping.Document; import org.springframework.data.document.mongodb.mapping.Document;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext; import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
@@ -48,7 +48,7 @@ public abstract class AbstractMongoConfiguration {
@Bean @Bean
public MongoDbFactory mongoDbFactory() throws Exception { public MongoDbFactory mongoDbFactory() throws Exception {
return new MongoDbFactoryBean(mongo(), defaultDatabaseName()); return new SimpleMongoDbFactory(mongo(), defaultDatabaseName());
} }
public String mappingBasePackage() { public String mappingBasePackage() {

View File

@@ -25,8 +25,9 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.document.mongodb.MongoDbFactoryBean; import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.document.mongodb.MongoFactoryBean; import org.springframework.data.document.mongodb.MongoFactoryBean;
import org.springframework.data.document.mongodb.SimpleMongoDbFactory;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@@ -47,62 +48,66 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
@Override @Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionRegistry registry = parserContext.getRegistry(); BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoDbFactoryBean.class); BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
// Host/Port used in this and the mongoFactory // UserCredentials
String host = element.getAttribute("host"); BeanDefinitionBuilder userCredentialsBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserCredentials.class);
if (!StringUtils.hasText(host)) { String username = element.getAttribute("username");
host = "localhost"; if (StringUtils.hasText(username)) {
} userCredentialsBuilder.addConstructorArgValue(username);
dbFactoryBuilder.addPropertyValue("host", host); } else {
String port = element.getAttribute("port"); userCredentialsBuilder.addConstructorArgValue(null);
if (!StringUtils.hasText(port)) { }
port = "27017"; String password = element.getAttribute("password");
} if (StringUtils.hasText(password)) {
dbFactoryBuilder.addPropertyValue("port", port); userCredentialsBuilder.addConstructorArgValue(password);
} else {
// Username/Password not always used (but is in CloudFoundry userCredentialsBuilder.addConstructorArgValue(null);
String username = element.getAttribute("username"); }
if (StringUtils.hasText(username)) {
dbFactoryBuilder.addPropertyValue("username", username); // host and port
} String host = element.getAttribute("host");
String password = element.getAttribute("password"); if (!StringUtils.hasText(host)) {
if (StringUtils.hasText(password)) { host = "localhost";
dbFactoryBuilder.addPropertyValue("password", password); }
} String port = element.getAttribute("port");
if (!StringUtils.hasText(port)) {
// Database name port = "27017";
String dbname = element.getAttribute("dbname"); }
if (!StringUtils.hasText(dbname)) {
dbname = "db"; // Database name
} String dbname = element.getAttribute("dbname");
dbFactoryBuilder.addPropertyValue("databaseName", dbname); if (!StringUtils.hasText(dbname)) {
dbname = "db";
// Create or reference a MongoFactory instance. }
// Also respect embedded "mongo:mongo" definitions.
String mongoRef = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(mongoRef)) { String mongoRef = element.getAttribute("mongo-ref");
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class); if (!StringUtils.hasText(mongoRef)) {
Element mongoEl = DomUtils.getChildElementByTagName(element, "mongo"); BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
if (null != mongoEl) { Element mongoEl = DomUtils.getChildElementByTagName(element, "mongo");
String overrideHost = mongoEl.getAttribute("host"); if (null != mongoEl) {
mongoBuilder.addPropertyValue("host", (StringUtils.hasText(overrideHost) ? overrideHost : host)); String overrideHost = mongoEl.getAttribute("host");
String overridePort = mongoEl.getAttribute("port"); mongoBuilder.addPropertyValue("host", (StringUtils.hasText(overrideHost) ? overrideHost : host));
mongoBuilder.addPropertyValue("port", (StringUtils.hasText(overridePort) ? overridePort : port)); String overridePort = mongoEl.getAttribute("port");
ParsingUtils.parseMongoOptions(parserContext, mongoEl, mongoBuilder); mongoBuilder.addPropertyValue("port", (StringUtils.hasText(overridePort) ? overridePort : port));
ParsingUtils.parseReplicaSet(parserContext, mongoEl, mongoBuilder); ParsingUtils.parseMongoOptions(parserContext, mongoEl, mongoBuilder);
} ParsingUtils.parseReplicaSet(parserContext, mongoEl, mongoBuilder);
else { }
mongoBuilder.addPropertyValue("host", host); else {
mongoBuilder.addPropertyValue("port", port); mongoBuilder.addPropertyValue("host", host);
} mongoBuilder.addPropertyValue("port", port);
registry.registerBeanDefinition(MONGO, mongoBuilder.getBeanDefinition()); }
mongoRef = MONGO; registry.registerBeanDefinition(MONGO, mongoBuilder.getBeanDefinition());
} mongoRef = MONGO;
dbFactoryBuilder.addPropertyValue("mongo", new RuntimeBeanReference(mongoRef)); }
return dbFactoryBuilder.getRawBeanDefinition(); dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef));
dbFactoryBuilder.addConstructorArgValue(dbname);
dbFactoryBuilder.addConstructorArgValue(userCredentialsBuilder.getBeanDefinition());
return dbFactoryBuilder.getRawBeanDefinition();
} }
} }

View File

@@ -7,7 +7,7 @@
<mongo:mongo host="localhost" port="27017"/> <mongo:mongo host="localhost" port="27017"/>
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean"> <bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.SimpleMongoDbFactory">
<constructor-arg name="mongo" ref="mongo"/> <constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/> <constructor-arg name="databaseName" value="database"/>
</bean> </bean>

View File

@@ -8,7 +8,7 @@
<property name="port" value="27017"/> <property name="port" value="27017"/>
</bean> </bean>
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean"> <bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.SimpleMongoDbFactory">
<constructor-arg name="mongo" ref="mongo"/> <constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/> <constructor-arg name="databaseName" value="database"/>
</bean> </bean>