How To Configure Multiple MongoDB Connectors in Spring Boot
Tags: kotlin, programming, softwaredevelopment, softwareengineering
Published: 2024-01-19 21:00:10

There are plenty of [online guides](https://dzone.com/articles/multiple-mongodb-connectors-with-spring-boot) explaining how to configure a Spring Boot application that connects to multiple MongoDBs. The common approach was to use [`MongoDbFactory`](https://docs.spring.io/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/MongoDbFactory.html), but this class was deprecated in Spring Data MongoDB 3.x, which introduced the [MongoDB 4.x driver](https://docs.mongodb.com/drivers/java).

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`](https://mvnrepository.com/artifact/org.springframework.boot/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](https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-mongodb/2.3.0.RELEASE).

If you are a Gradle user, add this dependency to your project's build file:

```shell
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:

```xml
<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](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#upgrading.2-3) 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:

```shell
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:

```shell
#--- 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`](https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html) [Spring Boot bean](https://www.baeldung.com/spring-bean) for each connection:

```kotlin
@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`](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/properties/ConfigurationProperties.html) 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`](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/mongo/MongoProperties.html) objects will have the value read from your configuration file.

The `MongoProperties` instances are used to establish the connections to the databases through [`SimpleMongoClientDatabaseFactory`](https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.html) and then create the required `MongoTemplate` instances.

The `MongoTemplate` class is the primary implementation of the [`MongoOperations`](https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoOperations.html) 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:

```kotlin
@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`](https://docs.spring.io/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/core/mapping/Document.html) representing the documents stored in the collection:

```kotlin
@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`](https://it.wikipedia.org/wiki/Data_Access_Object) layer class, you can define the retrieving logic as follows:

```kotlin
@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`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Qualifier.html) 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`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html).

Et voilà! No other lines of code are required.

### Using `MongoTemplate` Through `MongoRepository`

Repositories are one of the main concepts of [Spring Data](https://spring.io/projects/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](https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/repositories.html).

The implementation class of [`MongoRepository`](https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/repository/MongoRepository.html) 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:

```kotlin
@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:

```kotlin
@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](https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html) 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](https://writech.run/blog/how-to-configure-multiple-mongodb-connectors-in-spring-boot-669f36fe9d3e/)" appeared first on [Writech](https://writech.run)._