Search code examples
javaspringmongodbspring-bootembedded-database

How to make embedded mongodb keep the data on application shutdown?


I don't want to install the full mongodb, so I created a simple spring-boot application with the following pom:

    <!-- This dependency is to have an embedded mongodb -->
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <version>1.50.5</version>
    </dependency>

    <!-- while this provides a spring factory bean for the embedded mongodb -->
    <dependency>
        <groupId>cz.jirutka.spring</groupId>
        <artifactId>embedmongo-spring</artifactId>
        <version>RELEASE</version>
    </dependency>

    <!-- finally this one is the spring-boot starter for mongodb -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
        <version>${spring.boot.version}</version>
     </dependency>

It works fine, but on the application shutdown I lose all the data stored.

I noticed that the db is created inside of a temporary folder under C:\Users\myUser\AppData\Local\Temp\embedmongo-db-78beadc3-fa16-4101-afb1-ea7496f6f90c and, every time the application is restarted, another folder with different ID is created at the same location.

So, would it be possible to specify where the DB should be created so to keep the existing one and not lose all the data? Like you would do with h2 or sqllite?


Solution

  • Now it's possible see it.

    Next code just shows my solution to implement it.

    public class MongoInMemory {
     private int port;
     private String host;
     private MongodProcess process = null;
    
     public MongoInMemory(int port, String host){
        this.port = port;
        this.host = host;
     }
    
     @PostConstruct
     public void init() throws IOException {
        Storage storage = new Storage(
                System.getProperty("user.home") + "/.ttraining-storage", null, 0);
    
        IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
                .defaults(Command.MongoD)
                .artifactStore(new ExtractedArtifactStoreBuilder()
                        .defaults(Command.MongoD)
                        .download(new DownloadConfigBuilder()
                                .defaultsForCommand(Command.MongoD).build())
                        .executableNaming(new UserTempNaming()))
                .build();
    
        IMongodConfig mongodConfig = new MongodConfigBuilder()
                .version(Version.Main.PRODUCTION)
                .net(new Net(host, port, false))
                .replication(storage)
                .build();
    
        MongodStarter runtime = MongodStarter.getInstance(runtimeConfig);
        process = runtime.prepare(mongodConfig).start();
     }
    
     @PreDestroy
     public void stop(){
        process.stop();
     }
    }
    

    In configuration class define that as a bean

    @Bean
    public MongoInMemory mongoInMemory(
        @Value("${spring.data.mongodb.port}") int port,
        @Value("${spring.data.mongodb.host}")  String host) {
            return new MongoInMemory(port, host)
    }
    

    At last, remove embedded mongodb autoconfiguration in your entry point

    @SpringBootApplication(exclude = EmbeddedMongoAutoConfiguration.class)
    

    PS: Remove from dependecies cz.jirutka.spring:embedmongo-spring

    PSS: Tested on Spring-boot 2.0.0.RELEASE

    PSSS: Also you can define path as a property in application.properties and also it in constructor