53

Has anyone tried disabling autoconfiguration for mongodb in spring-boot?

I am trying out spring-boot with spring-data-mongodb; Using java based configuration; Using spring-boot 1.2.1.RELEASE, I import spring-boot-starter-web and its' parent pom for dependency management. I also import spring-data-mongodb (tried spring-boot-starter-mongodb as well).

I need to connect to two different MongoDB servers. So I need to configure two sets of instances for mongo connection, MongoTemplate etc. I also want to disable auto-configuration. Since I am connecting to multiple servers, I don't need to have a single default MongoTemplate and GridFsTemplate bean autoconfigured.

My main class looks like this:

@Configuration
@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@ComponentScan
//@SpringBootApplication  
public class MainRunner {

    public static void main(String[] args) {
        SpringApplication.run(MainRunner.class, args);
    }
}

My two mongo configuration classes look like this:

@Configuration
@EnableMongoRepositories(basePackageClasses = {Test1Repository.class},
        mongoTemplateRef = "template1",
        includeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test1Repository")}
)
public class Mongo1Config {

    @Bean
    public Mongo mongo1() throws UnknownHostException {
        return new Mongo("localhost", 27017);
    }
    
    @Primary
    @Bean
    public MongoDbFactory mongoDbFactory1() throws UnknownHostException {
        return new SimpleMongoDbFactory(mongo1(), "test1");
    }

    @Primary
    @Bean
    public MongoTemplate template1() throws UnknownHostException {
        return new MongoTemplate(mongoDbFactory1());
    }
}

and

@Configuration
@EnableMongoRepositories(basePackageClasses = {Test2Repository.class},
        mongoTemplateRef = "template2",
        includeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test2Repository")}
)
public class Mongo2Config {
    
    @Bean
    public Mongo mongo2() throws UnknownHostException {
        return new Mongo("localhost", 27017);
    }
    
    @Bean
    public MongoDbFactory mongoDbFactory2() throws UnknownHostException {
        return new SimpleMongoDbFactory(mongo2(), "test2");
    }
    
    @Bean
    public MongoTemplate template2() throws UnknownHostException {
        return new MongoTemplate(mongoDbFactory2());
    }
}

With this setup everything works. If I remove @Primary annotations from mongoDbFactory1 and template1 beans, application will fail with an exception that seems like autoconfiguration hasn't been disabled. Exception message is listed below:

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at com.fourexpand.buzz.web.api.template.MainRunner.main(MainRunner.java:26)
Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:98)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:75)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:378)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:155)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:157)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
    ... 7 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter': Injection of autowired dependencies failed; nested exception is  org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.core.io.ResourceLoader org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.resourceLoader; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gridFsTemplate' defined in class path resource [org/springframework/boot/autoconfigure/mongo/MongoDataAutoConfiguration.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.data.mongodb.MongoDbFactory]: : No qualifying bean of type [org.springframework.data.mongodb.MongoDbFactory] is defined: expected single matching bean but found 2: mongoDbFactory2,mongoDbFactory1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.data.mongodb.MongoDbFactory] is defined: expected single matching bean but found 2: mongoDbFactory2,mongoDbFactory1
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
im__
  • 677
  • 1
  • 5
  • 11
  • 1
    Do you have any other classes annotated with `SpringBootApplication` or `EnableAutoConfiguration`? – Andy Wilkinson Feb 26 '15 at 17:08
  • 4
    Try to exclude `MongoRepositoriesAutoConfiguration` as well. – Artem Bilan Feb 26 '15 at 17:13
  • @AndyWilkinson embarrassingly I did have another class annotated with SpringBootApplication. I had more than one entry point - main for testing and Apache Daemon + jsvc runner for production and I simply copy/pasted all the annotations instead of putting them to one common place... Excluding MongoRepositoriesAutoConfiguration turned out not to be necessary... – im__ Feb 26 '15 at 22:34
  • I just wanted to add that annotations used in the MainRunner class helped me trying to run a spring boot connected to two database using the code from https://falkenfighter.wordpress.com/2015/10/13/multiple-databases-with-spring-boot-mongodb-repositories/ – Francis Zabala Apr 28 '16 at 10:26
  • also exclude EmbeddedMongoAutoConfiguration.class and EmbeddedMongoProperties.class – Antoine Wils May 18 '16 at 15:46
  • My use case was similar: I wanted to enable embedded MongoDB, but only when running in the IDE. Note that that even the way to use embedded MongoDB with autoconfiguration has changed [since Spring Boot 2.7](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes#springmongodbembeddedfeatures-configuration-property-removed). I wrote up a blog post using some of the pointers I found here, as well some other tips that may be helpful, in [Embedded MongoDB Only in IDE using Spring Boot 3.x](https://www.garretwilson.com/blog/2023/04/02/embedded-mongodb-ide-spring-boot-3). – Garret Wilson Apr 02 '23 at 21:18

6 Answers6

45

This is how I do it:

@SpringBootApplication(exclude = {
  MongoAutoConfiguration.class, 
  MongoDataAutoConfiguration.class
})

or as suggested by Dan Oak:

spring.autoconfigure.exclude= \
  org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
  org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
user5365075
  • 2,094
  • 2
  • 25
  • 42
11

As pointed out by Andy Wilkinson in comments, when using EnableAutoConfiguration with exclude list make sure there are no other classes annotated with EnableAutoConfiguration or SpringBootApplication.

im__
  • 677
  • 1
  • 5
  • 11
7

My use case was slightly different. I had a requirement for 2 different databases in the same project. I extended the auto configuration classes and added a profile annotation.

@Profile("mongo")
@Configuration
public class CustomMongoAutoConfiguration extends MongoAutoConfiguration {

    public CustomMongoAutoConfiguration(
        MongoProperties properties,
        ObjectProvider<MongoClientOptions> options,
        Environment environment) {
        super(properties,options,environment);
    }
}

And

@Profile("mongo")
@Configuration
@EnableConfigurationProperties(MongoProperties.class)
public class CustomMongoDataAutoConfiguration extends MongoDataAutoConfiguration {

    public CustomMongoDataAutoConfiguration(
        ApplicationContext applicationContext,
        MongoProperties properties) {
        super(applicationContext,properties);
    }

}
Miguel Pereira
  • 1,781
  • 16
  • 14
  • I have two dbs as well and I can confirm this works. No spring boot app excluded field changes necessary. This should be the real solution since the other seems like a hack to me. I had issues setting up Mongobee bean for two databases and this solved the reported issue of two Mongobee beans available. – edin-m Oct 19 '18 at 13:45
  • Another note, I had to give Mongobee's beans a name otherwise, it picked up only one Mongobee. – edin-m Oct 19 '18 at 14:52
  • I wanted to have just a single configuration, but to only enable it in a certain profile. Using the new [Spring 3 embedded MongoDB](https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo.spring/tree/spring-3.0.x), I still needed `@SpringBootApplication(exclude = {EmbeddedMongoAutoConfiguration.class})` in my main application class or I would get an error about a bean being configured twice, as otherwise it tried to register the underlying `EmbeddedMongoAutoConfiguration` as well. – Garret Wilson Apr 02 '23 at 21:15
6

Try to Run application in Debug mode. It happens when MongoDB dependant configaration is trying to instantiate but respective bean not present. In My case I have excluded MongoDataAutoConfiguration.class and MongoRepositoriesAutoConfiguration.class, to get the application run.

@SpringBootApplication
@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class,MongoDataAutoConfiguration.class})
public class SomeApplication {
//...
}
user634545
  • 9,099
  • 5
  • 29
  • 40
2

Spring Boot 2.3.x:

spring.autoconfigure.exclude[0]: org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
spring.autoconfigure.exclude[1]: org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration

Reactive:

spring.autoconfigure.exclude[0]: org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration
spring.autoconfigure.exclude[1]: org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration
emvidi
  • 1,210
  • 2
  • 14
  • 18
1

Same as https://stackoverflow.com/a/45929916/5213837 with https://stackoverflow.com/a/49980868/5213837, Spring boot 2.3/Kotlin

@SpringBootApplication(exclude = [MongoAutoConfiguration::class, MongoDataAutoConfiguration::class]
@Profile("mongo")
@Configuration
class CustomMongoAutoConfiguration: MongoAutoConfiguration() {
    override fun mongo(
        properties: MongoProperties?,
        environment: Environment?,
        builderCustomizers: ObjectProvider<MongoClientSettingsBuilderCustomizer>?,
        settings: ObjectProvider<MongoClientSettings>?
    ): MongoClient {
        return super.mongo(properties, environment, builderCustomizers, settings)
    }
}
@Profile("mongo")
@Configuration
@EnableConfigurationProperties(MongoProperties::class)
class CustomMongoDataAutoConfiguration : MongoDataAutoConfiguration()