Connecting to MongoDB with Spring
One of the first tasks when using MongoDB and Spring is to create a com.mongodb.MongoClient
or com.mongodb.client.MongoClient
object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections.
For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs here as well as the detailed documentation here. |
Registering a Mongo Instance by using Java-based Metadata
The following example shows an example of using Java-based bean metadata to register an instance of a com.mongodb.MongoClient
:
com.mongodb.MongoClient
object using Java-based bean metadata@Configuration
public class AppConfig {
/*
* Use the standard Mongo driver API to create a com.mongodb.MongoClient instance.
*/
public @Bean MongoClient mongoClient() {
return new MongoClient("localhost");
}
}
This approach lets you use the standard com.mongodb.MongoClient
instance, with the container using Spring’s MongoClientFactoryBean
. As compared to instantiating a com.mongodb.MongoClient
instance directly, the FactoryBean
has the added advantage of also providing the container with an ExceptionTranslator
implementation that translates MongoDB exceptions to exceptions in Spring’s portable DataAccessException
hierarchy for data access classes annotated with the @Repository
annotation. This hierarchy and the use of @Repository
is described in Spring’s DAO support features.
The following example shows an example of a Java-based bean metadata that supports exception translation on @Repository
annotated classes:
com.mongodb.MongoClient
object by using Spring’s MongoClientFactoryBean and enabling Spring’s exception translation support@Configuration
public class AppConfig {
/*
* Factory bean that creates the com.mongodb.MongoClient instance
*/
public @Bean MongoClientFactoryBean mongo() {
MongoClientFactoryBean mongo = new MongoClientFactoryBean();
mongo.setHost("localhost");
return mongo;
}
}
To access the com.mongodb.MongoClient
object created by the MongoClientFactoryBean
in other @Configuration
classes or your own classes, use a private @Autowired Mongo mongo;
field.
Registering a Mongo Instance by Using XML-based Metadata
While you can use Spring’s traditional <beans/>
XML namespace to register an instance of com.mongodb.MongoClient
with the container, the XML can be quite verbose, as it is general-purpose. XML namespaces are a better alternative to configuring commonly used objects, such as the Mongo instance. The mongo namespace lets you create a Mongo instance server location, replica-sets, and options.
To use the Mongo namespace elements, you need to reference the Mongo schema, as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation=
"http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Default bean name is 'mongo' -->
<mongo:mongo-client host="localhost" port="27017"/>
</beans>
The following example shows a more advanced configuration with MongoClientOptions
(note that these are not recommended values):
<beans>
<mongo:mongo-client host="localhost" port="27017">
<mongo:client-options connections-per-host="8"
threads-allowed-to-block-for-connection-multiplier="4"
connect-timeout="1000"
max-wait-time="1500}"
auto-connect-retry="true"
socket-keep-alive="true"
socket-timeout="1500"
slave-ok="true"
write-number="1"
write-timeout="0"
write-fsync="true"/>
</mongo:mongo-client>
</beans>
The following example shows a configuration using replica sets:
com.mongodb.MongoClient
object with Replica Sets<mongo:mongo-client id="replicaSetMongo" replica-set="127.0.0.1:27017,localhost:27018"/>
The MongoDbFactory Interface
While com.mongodb.MongoClient
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.client.MongoDatabase
object and access all the functionality of a specific MongoDB database instance. Spring provides the org.springframework.data.mongodb.core.MongoDbFactory
interface, shown in the following listing, to bootstrap connectivity to the database:
public interface MongoDbFactory {
MongoDatabase getDb() throws DataAccessException;
MongoDatabase getDb(String dbName) throws DataAccessException;
}
The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the MongoDbFactory
interface. In turn, you can use the MongoDbFactory
instance to configure MongoTemplate
.
Instead of using the IoC container to create an instance of MongoTemplate, you can use them in standard Java code, as follows:
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 MongoClient(), "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.
Use SimpleMongoClientDbFactory when choosing com.mongodb.client.MongoClient as the entrypoint of choice.
|
Registering a MongoDbFactory
Instance by 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. The following listing shows a simple example:
@Configuration
public class MongoConfiguration {
public @Bean MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClient(), "database");
}
}
MongoDB Server generation 3 changed the authentication model when connecting to the DB. Therefore, some of the configuration options available for authentication are no longer valid. You should use the MongoClient
-specific options for setting credentials through MongoCredential
to provide authentication data, as shown in the following example:
@Configuration
public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfiguration {
@Override
public String getDatabaseName() {
return "database";
}
@Override
@Bean
public MongoClient mongoClient() {
return new MongoClient(singletonList(new ServerAddress("127.0.0.1", 27017)),
singletonList(MongoCredential.createCredential("name", "db", "pwd".toCharArray())));
}
}
In order to use authentication with XML-based configuration, use the credentials
attribute on the <mongo-client>
element.
Username and password credentials used in XML-based configuration must be URL-encoded when these contain reserved characters, such as : , % , @ , or , .
The following example shows encoded credentials:
m0ng0@dmin:mo_res:bw6},Qsdxx@admin@database → m0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database
See section 2.2 of RFC 3986 for further details.
|
As of MongoDB java driver 3.7.0 there is an alternative entry point to MongoClient
via the mongodb-driver-sync artifact.
com.mongodb.client.MongoClient
is not compatible with com.mongodb.MongoClient
and does not longer support
the legacy DBObject
codec. Therefore, it cannot be used with Querydsl
and requires a different configuration.
You can use AbstractMongoClientConfiguration
to leverage the new MongoClients
builder API.
@Configuration
public class MongoClientConfiguration extends AbstractMongoClientConfiguration {
@Override
protected String getDatabaseName() {
return "database";
}
@Override
public MongoClient mongoClient() {
return MongoClients.create("mongodb://localhost:27017/?replicaSet=rs0&w=majority");
}
}
Registering a MongoDbFactory
Instance by Using XML-based Metadata
The mongo
namespace provides a convenient way to create a SimpleMongoDbFactory
, as compared to using the <beans/>
namespace, as shown in the following example:
<mongo:db-factory dbname="database">
If you need to configure additional options on the com.mongodb.MongoClient
instance that is used to create a SimpleMongoDbFactory
, you can refer to an existing bean by using the mongo-ref
attribute as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a MongoTemplate
:
<context:property-placeholder location="classpath:/com/myapp/mongodb/config/mongo.properties"/>
<mongo:mongo-client host="${mongo.host}" port="${mongo.port}">
<mongo:client-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-client>
<mongo:db-factory dbname="database" mongo-ref="mongoClient"/>
<bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>