简体   繁体   中英

Embeded flapdoodle MongoDB process won't stop

I am using an flapdoodle embedded MongoDB instance in my application.

The embedded MongoDB starts up and works as expected, but the process of the embedded instance won't stop when the application is being stopped or the integration tests are over.

I am using the class below to manage the state of the embedded MongoDB instance. Is there something missing to properly stop the embedded MongoDB? Can we start the process of the embedded MongoDB instance as a daemon (so it won't keep the running, even when the application is being stoppped)?

package ch.somePackage.configuration;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.Objects;

@Configuration
public class DbConfiguration  {

    final static Logger logger = LoggerFactory.getLogger(DbConfiguration.class);

    private static final ConnectionString CONNECTION_STRING = new ConnectionString("mongodb://localhost:12345/some-db");

    @Bean
    public MongoHolder mongoHolder() {
        return new MongoHolder();
    }

    public static class MongoHolder {

        private MongoClient mongoClient;
        private MongodExecutable mongodExecutable;
        private MongodProcess mongod;

        @PostConstruct
        public void init() throws IOException {
            final MongodStarter starter = MongodStarter.getDefaultInstance();

            final String bindIp = "localhost";
            final int port = 12345;
            final IMongodConfig mongodConfig = new MongodConfigBuilder()
                    .version(Version.Main.PRODUCTION)
                    .net(new Net(bindIp, port, Network.localhostIsIPv6()))
                    .build();

            try {
                mongodExecutable = starter.prepare(mongodConfig);
                mongod = mongodExecutable.start();
                mongoClient = new MongoClient(bindIp, port);
                logger.info("Started embedded mongo.");
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }

        @PreDestroy
        public final synchronized void destroy() {
            if (mongodExecutable != null) {
                logger.info("Stopping embedded mongo.");
                mongoClient.close();
                mongodExecutable.stop();
                mongod.stop();
                logger.info("Stopped embedded mongo.");
            }
        }

        public MongoClient getMongoClient() {
            return mongoClient;
        }
    }

    @Bean
    public MongoDatabase mongoDatabase(final MongoHolder mongoHolder) {
        return mongoHolder.getMongoClient().getDatabase(Objects.requireNonNull(CONNECTION_STRING.getDatabase()));
    }
}

I had the same issue when using flapdoodle embedded MongoDB for development and while running the Spring application via gradle bootRun . After stopping the process, the MongoDB server survived and with more and more runs instances piled up and also the data within the MongoDB stayed.

After quite some searching and trying out things I was able to solve the issue based on the answers provided in https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/issues/212

My MongoDB Configuration Class looks quite similar and the key to the solution was to wait for MongodProcess mongod to properly stop through checking with mongod.isProcessRunning() . The surrounding while loop is a bit hacky, but it works for me:

@Configuration
@Profile("dev")
public class EmbeddedMongoConfig {

    Logger logger = LoggerFactory.getLogger(EmbeddedMongoConfig.class);

    private static final String CONNECTION_STRING = "mongodb://%s:%d";
    private static final String HOST = "localhost";
    private static final int PORT = 27017;


    private MongodExecutable mongodExecutable;
    private MongodProcess mongod;
    private MongoClient client;

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        ImmutableMongodConfig mongoDbConfig = MongodConfig.builder()
                .version(Version.Main.PRODUCTION)
                .net(new Net(HOST, PORT, Network.localhostIsIPv6()))
                .build();

        MongodStarter starter = MongodStarter.getDefaultInstance();

        mongodExecutable = starter.prepare(mongoDbConfig);
        mongod = mongodExecutable.start();
        client = MongoClients.create(String.format(CONNECTION_STRING, HOST, PORT));

        return new MongoTemplate( client, "sampledatabase");
    }


    /*
     * solution found here: https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/issues/212
     */
    @PreDestroy
    public void shutdownGracefully() {
        if (client != null)
            client.close();
        if (mongod != null)
            try {
                mongod.stop();
            } catch (IllegalStateException e) {
                logger.error("Can't stop mongod", e);
            }
        if (mongod != null) {
            int limit = 5;
            int counter = 0;
            while (mongod.isProcessRunning() && counter < limit) {
                try {
                    counter++;
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
        if (mongodExecutable != null) {
            try {
                mongodExecutable.stop();
            } catch (IllegalStateException e) {
                logger.error("Can't stop mongodExecutable", e);
            }
        }
    }
}

Maybe it can still help someone else who stumbles upon the same issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM