MongoDB
SeedStack MongoDB add-on provides integration of MongoDB Java clients your application to connect with MongoDB instances.
Dependencies
Add the following dependency:
<dependency>
<groupId>org.seedstack.addons.mongodb</groupId>
<artifactId>mongodb</artifactId>
</dependency>
Show version
dependencies {
compile("org.seedstack.addons.mongodb:mongodb:3.1.3")
}
You also need to add the MongoDB Java client:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>...</version>
</dependency>
dependencies {
compile("org.mongodb:mongo-java-driver:...")
}
You can choose to use the MongoDB asynchronous client instead (or in addition as you can mix asynchronous and synchronous clients in the same application):
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>...</version>
</dependency>
dependencies {
compile("org.mongodb:mongodb-driver-async:...")
}
Configuration
Configuration is done by declaring one or more clients:
mongoDb:
# Configured clients with the name of the client as key
clients:
client1:
# If true, the client is considered asynchronous (defaults to false)
async: (boolean)
# URI to connect the client to
uri: (String)
# List of hosts to connect the client to (only considered if no uri is specified)
hosts: (List<String>)
# Only when using hosts: list of credentials to use (formatted as '[authMechanism/]dbName:user:password')
credentials: (List<String>)
# Only for synchronous clients: options based on MongoClientOptions class
options:
...
# Only for asynchronous clients: options based on the various Settings classes
settings:
...
# Databases available through this client with the name of the database as key
databases:
db1:
# If specified the database will be injectable through this alias instead of its original name
# This is useful for database name collisions between multiple clients
alias: (String)
To dump the mongoDb
configuration options:
mvn -q -Dargs="mongoDb" seedstack:config
As MongoDB has a different Java driver for synchronous and asynchronous clients, the type of a client will determine how
it can be configured and used. Clients use the synchronous driver
by default, to switch to the asynchronous driver, set
the async
configuration property to true
.
URI connection string
The uri
property is formatted as below:
mongoDb:
clients:
client1:
uri: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
URI allows to directly specify a set of options common to synchronous and asynchronous clients. More information about the URI and its options can be found here.
When no port is specified, the default MongoDB port is used (27017).
Explicit hosts
As an alternative a client can be configured by directly specifying the MongoDB host(s):
mongoDb:
clients:
client1:
hosts: [ host1:27017, host2 ]
In this case, the client options must be specified using additional properties, which a are different for synchronous and asynchronous clients. See the Synchronous client options and Asynchronous client options sections below for more information.
When no port is specified, the default MongoDB port is used (27017).
When configuring the connection with explicit hosts, connection credentials can be specified as the following:
mongoDb:
clients:
client1:
hosts: [ host1:27017, host2 ]
credentials: [ db1:user1:password1 ]
This will authenticate with the username user1
and the password password1
. The user will be looked up in the db1
database. The authentication mechanism will be automatically selected. To force an authentication mechanism use the
following syntax:
mongoDb:
clients:
client1:
hosts: [ host1:27017, host2 ]
credentials: [ mechanism/db1:user1:password1 ]
The available authentication mechanisms are PLAIN
, MONGODB_CR
, SCRAM_SHA_1
, MONGODB_X509
and GSSAPI
.
It is recommended to avoid specifying the authentication mechanism as it will be automatically selected. Also note that often, only one credential is enough.
Databases
You can choose to inject and use the MongoClient
object(s) directly and access the database(s) programmatically. As a
convenience, the add-on also allows to inject the MongoDatabase
object(s) provided they are configured as follow:
mongoDb:
clients:
client1:
uri: ...
databases: [ db1, db2 ]
Each declared database can then be injected (see the usage section to know how to inject them). Database names must be unique across the application so you can encounter a situation when multiple configured clients may need to access databases with the same name. In that case, you can use the alias feature. Consider the following clients:
mongoDb:
clients:
client1:
uri: ...
databases: [ db1, db2 ]
client2:
uri: ...
databases: [ db2, db3 ]
The database named db2
exists in MongoDB instances accessed by both client1
and client2
. To resolve this ambiguity,
one of the db2
databases must be aliased in the application:
mongoDb:
clients:
client1:
uri: ...
databases: [ db1, db2 ]
client2:
uri: ...
databases:
db2:
alias: db2bis
db3:
In this example, the db2
database present on the MongoDB instance accessed by client2
will be referred in the
application by the db2bis
name. Note that you can use this feature even when there are no name collision.
Synchronous client options
Additional options can be specified on synchronous clients with the options
property of the client.
All the options from the MongoClientOptions.Builder class are available. Each method of the builder translates to an option of the same name. Consider the following example:
mongoDb:
clients:
client1:
uri: ...
options:
connectionsPerHost: 75
This will invoke the connectionsPerHost()
method on the option builder with the value 75
converted to an integer.
If you use an URI configuration, you can combine the URI options with the options
property. The latter will
will complement their URI counterpart and override them if present in both.
Asynchronous client options
Additional options can be specified on asynchronous clients with the settings
property:
mongoDb:
clients:
client1:
async: true
uri: ...
settings:
namespace1:
setting1: value1
namespace2:
setting2: value2
setting3: value3
All the settings from the MongoClientSettings.Builder
builder and its sub-builders are available. Each sub-builder translates
to a setting namespace and each of the builders method translates to a particular setting. The list of the builders and
their corresponding namespace is:
Namespace | Builder |
---|---|
cluster | ClusterSettings.Builder |
connectionPool | ConnectionPoolSettings.Builder |
socket | SocketSettings.Builder |
heartbeatSocket | SocketSettings.Builder |
server | ServerSettings.Builder |
ssl | SslSettings.Builder |
Consider the following example:
mongoDb:
clients:
client1:
async: true
uri: ...
settings:
connectionPool:
maxSize: 75
This will invoke the maxSize()
method on a ConnectionPoolSettings.Builder
instance with the value 75
converted to
an integer. This builder instance will in turn be be set on a MongoClientSettings.Builder
instance via the connectionPoolSettings()
method.
- The global settings directly available on
MongoClientSettings.Builder
can be specified without namespace. More information on the global builder here. - The
cluster.hosts
andcredentialList
settings are ignored since they are already mapped from thehosts
and thecredentials
properties.
Usage
As MongoDB does not support transactions, usage simply consists in injecting a MongoClient
or a MongoDatabase
object
and using it accordingly to the MongoDB documentation. As an example you can inject the client as the following:
public class SomeClass {
@Inject
@Named("client1")
private MongoClient client1;
}
This will inject the configured MongoDB client named client1
. You can also inject a database directly as the following:
public class SomeClass {
@Inject
@Named("db1")
private MongoDatabase db1;
}
This will inject the configured MongoDB database named db1
. Note that you must use the aliased name instead of the
real database name if you aliased it in the configuration (see the databases section for information
about aliases).
- If your client or database is configured as synchronous (the default) you must inject the
com.mongodb.MongoClient
andcom.mongodb.client.MongoDatabase
classes. - If your client or database is configured as asynchronous, you must inject the
com.mongodb.async.client.MongoClient
andcom.mongodb.async.client.MongoDatabase
classes instead.
Recommendations
Connection timeout
The default configuration for the MongoDB driver is to make pooled connections stay forever alive, which may lead to SocketException («Connection timed up») errors when connecting to remote/cloud MongoDB servers. This seems OK in a local network context.
In a cloud context, remote DB servers (or intermediate network components) may kill the pooled connections after a period of time. The application won’t detect it until it tries to use the connection. The application will recover from the error as the pool will be discarded and new connections will be open, but the ongoing operation that tried to use the broken connection will fail and get lost in the process.
Using the connection option «maxIdleTimeMS» in the connection URI, or the client options
yaml section will avoid this
kind of problem. Example of a URI setting this option:
mongoDb:
clients:
myClient:
uri: mongodb://username:password@host:port/dbName?maxIdleTimeMS=120000
120 seconds is recommended in MongoDB documentation for the related tcp_keepalive
problems, so it can safely be
applied to this option. See http://docs.mongodb.org/manual/reference/connection-string/#maxIdleTimeMS