There are plenty of online guides explaining how to configure a Spring Boot application that connects to multiple MongoDBs. The common approach was to use MongoDbFactory
, but this class was deprecated in Spring Data MongoDB 3.x, which introduced the MongoDB 4.x driver.
So, let's see how to configure multiple MongoDB data sources in Spring Boot using Spring Data MongoDB 3.x.
Please note that code will be written in Kotlin, but the same result can be achieved in Java as well. Similarly, I am going to use only two different MongoDB connections in this tutorial, but the approach works with any number of databases.
Adding the Required Dependencies
First, you need to add spring-boot-starter-data-mongodb
to your project's dependencies. Use at least the 2.3.0 version since the MongoDB Driver 4.x was introduced in Spring Boot Starter Data MongoDB 2.3.0.RELEASE.
If you are a Gradle user, add this dependency to your project's build file:
compile "org.springframework.boot:spring-boot-starter-data-mongodb:2.3.0.RELEASE"
Otherwise, if you are a Maven user, add the following dependency to your project's build POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
Now, you have all you need to use MongoDB in Spring Boot.
Defining Multiple MongoTemplate
Instances
If you already have multiple MongoTemplates
but you want to upgrade to Spring Data MongoDB 3.x, I recommend reading the docs first. Otherwise, you can start from scratch by following the next few steps.
First, you need to define all your MongoDB connection details in your application.properties
file.
The host
and port
configurations are no longer supported in the MongoDB 4.x driver, so you need to use a single URI providing all the required configurations with this format:
mongodb://<username>:<password>@<host>:<port>/<db_name>
Please note that <username>:<password>@
is optional and you should only use it for authenticated connections.
So, your application.properties
should contain something like this:
#--- Primary MongoDB ---#
spring.data.mongodb.uri=mongodb://admin:password@127.0.0.1:27017/primary
#--- Secondary MongoDB ---#
mongodb.uri=mongodb://admin:password@127.0.0.1:27017/secondary
Now, it is time to add a new Spring Boot configuration file in which you will define a MongoTemplate
Spring Boot bean for each connection:
@Configuration
class MultipleMongoConfig {
@Primary
@Bean(name = ["primaryMongoProperties"])
@ConfigurationProperties(prefix = "spring.data.mongodb")
fun getPrimary() : MongoProperties {
return MongoProperties()
}
@Bean(name = ["secondaryMongoProperties"])
@ConfigurationProperties(prefix = "mongodb")
fun getSecondary() : MongoProperties {
return MongoProperties()
}
@Primary
@Bean(name = ["primaryMongoTemplate"])
fun primaryMongoTemplate() : MongoTemplate {
return MongoTemplate(primaryMongoDatabaseFactory(getPrimary()))
}
@Bean(name = ["secondaryMongoTemplate"])
fun secondaryMongoTemplate() : MongoTemplate {
return MongoTemplate(secondaryMongoDatabaseFactory(getSecondary()))
}
@Primary
@Bean
fun primaryMongoDatabaseFactory(mongo : MongoProperties) : MongoDatabaseFactory {
return SimpleMongoClientDatabaseFactory(
mongo.uri
)
}
@Bean
fun secondaryMongoDatabaseFactory(mongo : MongoProperties) : MongoDatabaseFactory {
return SimpleMongoClientDatabaseFactory(
mongo.uri
)
}
}
The @ConfigurationProperties
annotation works with hierarchical properties that all have the same prefix defined in your configuration file.
Spring Boot will automatically bind any property defined in the application.properties
file that has the prefix declared in the annotation and the same name as one of the fields in the target class. This means that the uri
field of the MongoProperties
objects will have the value read from your configuration file.
The MongoProperties
instances are used to establish the connections to the databases through SimpleMongoClientDatabaseFactory
and then create the required MongoTemplate
instances.
The MongoTemplate
class is the primary implementation of the MongoOperations
interface and provides a basic set of MongoDB operations. You can use a MongoTemplate
object to do aggregations, sorting, and to find the desired documents based on multiple criteria in the database it refers to.
Lastly, you have to disable Spring Boot autoconfiguration for Mongo. You can achieve this by adding these lines of code on top of your Spring Boot application's main class:
@SpringBootApplication(exclude = [
MongoAutoConfiguration::class,
MongoDataAutoConfiguration::class
])
Using the MongoTemplate
Instances
Using MongoTemplate
directly
MongoTemplate
provides a basic API to the underlying persistence engine and can be used to execute queries. All you need to use it in such a way is a working instance.
Let's assume you want to retrieve all the authors saved in a collection named authors
placed in the secondary MongoDB database by a specific surname.
Now, you need an Author
class annotated with @Document
representing the documents stored in the collection:
@Document(collection = "author")
class Author {
@get:Id
@get:Field("_id")
var id: String? = null
@get:Field("name")
var name: String? = null
@get:Field("surname")
var surname: String? = null
}
Then, in a DAO
layer class, you can define the retrieving logic as follows:
@Repository
class AuthorDao {
@Autowired
@Qualifier("secondaryMongoTemplate")
protected lateinit var secondaryMongoTemplate : MongoTemplate
fun findBySurname(surname): List<Author> {
val query = Query()
query.addCriteria(
Criteria.where("surname").`is`(surname)
)
return secondaryMongoTemplate.find(query, Author::class.java)
}
}
Notice that the @Qualifier
annotation is required to select the desired MongoTemplate
instance by Bean
name. Without it, Spring Boot would choose the primaryMongoTemplate
object defined in MultipleMongoConfig
because it is marked with @Primary
.
Et voilà! No other lines of code are required.
Using MongoTemplate
Through MongoRepository
Repositories are one of the main concepts of Spring Data and a way to reduce the effort to implement data access layers by avoiding boilerplate code. For further reading, I recommend the docs.
The implementation class of MongoRepository
harnesses a MongoTemplate
instance at runtime.
To specify which MongoTemplate
bean has to be used, you need extra configurations. In particular, you have to define a new @Configuration
file for each MongoTemplate
instance.
This is what the configuration file to enable repositories working with primaryMongoTemplate
looks like:
@Configuration
@EnableMongoRepositories(
basePackages = ["com.example.yourproject.primary.repositories"],
mongoTemplateRef = "primaryMongoTemplate"
)
class PrimaryMongoDBRepositoryConfig
And this is what the configuration file to enable repositories to work with secondaryMongoTemplate
looks like:
@Configuration
@EnableMongoRepositories(
basePackages = ["com.example.yourproject.secondary.repositories"],
mongoTemplateRef = "secondaryMongoTemplate"
)
class SecondarMongoDBRepositoryConfig
Please, note that basePackages
must point to the packages where all your repositories related to a specific mongoTemplateRef
are placed.
Now you have all you need to start using MongoDB repositories in Spring Boot. This article is not aimed at showing that and I suggest reading the docs instead.
Conclusion
In today's article, we looked at how to define multiple MongoTemplates
using the MongoDB 4.x
driver in Spring Boot from the ground up. At the same time, I showed how to use them directly or through MongoRepository
to execute all the queries you need to retrieve and persist data.
Thanks for reading! I hope that you found this article helpful.
The post "How To Configure Multiple MongoDB Connectors in Spring Boot" appeared first on Writech.
Top comments (0)