1

I am experiencing some problems using Spring Boot and MongoDB external driver. I can't use the project Spring Data MongoDB, because I need to use the ufficial async driver given by Mongo. However, I need to use Spring Boot, because the module I am developing is part of a bigger project using this library.

Here is my pom.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>tx-view</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- omissis -->

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-async</artifactId>
            <version>${mongodb.version}</version>
        </dependency>
     </dependencies>

    <build>
        <plugins>
            <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

In detail, I am using Spring Boot 1.4.1 and Mongo Async Driver 3.2.2.

Here is my application.

@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class TxViewApplication {
    public static void main(String[] args) {
        SpringApplication.run(TxViewApplication.class, args);
    }

    @Value("${mongo.uri}")
    private String mongoUri;

    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create(mongoUri);
    }
}

It follows the only (empty) test I have at the moment.

@SpringBootTest
@RunWith(SpringRunner.class)
public class ApplicationTest {
    @Test
    public void loadContext() throws Exception {}
}

I have no other code in this project. When I run the test, I have the following error:

2016-11-22 15:43:58.597  INFO 4572 --- [null'}-db:27017] org.mongodb.driver.cluster               : Exception in monitor thread while connecting to server db:27017

com.mongodb.MongoException: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.

at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:125) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:128) ~[mongodb-driver-core-3.2.2.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Caused by: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.

at sun.nio.ch.Iocp.translateErrorToIOException(Iocp.java:309) ~[na:1.8.0_101]
at sun.nio.ch.Iocp.access$700(Iocp.java:46) ~[na:1.8.0_101]
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:399) ~[na:1.8.0_101]
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_101]
... 1 common frames omitted

As you can see, I have properly inserted the exclude clause in the SpringBootApplication annotation in order to stop Spring Boot to try handle its own the connection to Mongo, as suggested in Mongo tries to connect automatically to port 27017(localhost).

I have also noticed that I started to have the error after the addition to the pom.xml of the dependency to spring-boot-starter-web.

How can I inhibit Spring Boot to try to connect automatically to Mongo at startup? The same problem is present with the synchronous version of MongoDB driver.

--- EDIT ---

I have also try to build a wrapper around the async.MongoClient object, in this way:

public class MongoWrapper {
    private final MongoClient mongo;

    public MongoWrapper() {
        mongo = MongoClients.create();
    }

    public MongoClient getMongo() {
        return mongo;
    }
}

The configuration was changed accordingly.

@Bean
public MongoWrapper mongo() {
    return new MongoWrapper();
}

Unfortunately, nothing had changed. Spring Boot seems to intercept the MongoClient object also in this way :(

Thanks a lot.

Community
  • 1
  • 1
riccardo.cardin
  • 7,971
  • 5
  • 57
  • 106
  • maybe `SpringBootTest` does not use `TxViewApplication` as the source of the context because you have another `@SpringBootConfiguration` somewhere else. If you exclude mongo, why do you define a `MongoClient` in the same class then? – Stephane Nicoll Nov 22 '16 at 17:29
  • The code that I have posted it's the only one in the project. I merged the configuration in the same class that starts the application to have less code to show. Did you mean that I have no to define any object of type MongoClient in the Spring configuration? – riccardo.cardin Nov 22 '16 at 20:54
  • @StephaneNicoll, how do you suggest to integrate the async java driver of MongoDB with Spring Boot? – riccardo.cardin Nov 22 '16 at 21:57
  • If you exclude the auto-config, it does not make sense that we attempt to connect on startup. Can you share a sample? – Stephane Nicoll Nov 23 '16 at 08:36
  • @StephaneNicoll I shared a demo project on [GitHub](https://github.com/rcardin/spring-boot-mongodb-async). The `pom.xml` was generated using Spring Initializr. Then I add the dependency to mongo async driver. If you try to run `DemoApplicationTests` you will be able to replicate the error. Thanks a lot. – riccardo.cardin Nov 23 '16 at 08:58
  • "Spring Boot seems to intercept the MongoClient object also in this way". Of course, as your *MongoWrapper* constructor calls *MongoClients.create()* – Tome Nov 23 '16 at 12:43

2 Answers2

1

You have a MongoClient bean in your own configuration which does not make any sense to me if you've excluded the auto-configuration.

I've commented out the @Bean definition in your own config and no attempt to connect to Mongo is performed now. I am not sure I answer to your question and you're probably looking for something else but if you don't want to use mongo, don't define a MongoClient in your own config!

Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
  • I DO want to use Mongo! But I DO NOT want Spring Boot handling connection to it for me. Then you're saying that I cannot use Spring dependency injection mechanisms to build a `MongoClient` instance without Spring Boot intercepting it? – riccardo.cardin Nov 23 '16 at 11:53
  • Spring boot doesn't do anything. The fact you create this bean definition makes it connect on startup. Spring Boot is not responsible of that at all. – Stephane Nicoll Nov 23 '16 at 11:55
  • Mongo driver documentation states that the simple creation of a MongoClient does not Force db connection. How do you explain this? – riccardo.cardin Nov 23 '16 at 11:58
  • 1
    Oh so if the mongo documentation states that, it must be Spring Boot's fault? Look at the call stack, there is not a single element related to Spring. Replace your main with the following code and you'll have the exception: ```public static void main(String[] args) throws IOException { MongoClient mongoClient = MongoClients.create(); System.in.read(); }``` – Stephane Nicoll Nov 23 '16 at 12:04
  • You're right, I am sorry. I trusted the Mongo client documentation. Running the example code you gave in the last comment rised the exception too :( – riccardo.cardin Nov 23 '16 at 13:22
  • 1
    I will try to ask to MongoDB people what's going on. Thanks a lot for the patience. – riccardo.cardin Nov 23 '16 at 13:28
1

This helped us to disable async java driver of MongoDB to use default configuration:

@EnableAutoConfiguration(exclude = {MongoReactiveAutoConfiguration.class})
riccardo.cardin
  • 7,971
  • 5
  • 57
  • 106
Alexei Y
  • 11
  • 1