I have a spring boot application that has multiple Modules with their respective Tests and Test Context. I frequently face this Exception(race condition as it seems).

[...]
Caused by: de.flapdoodle.embed.process.exceptions.DistributionException: 

-----------------------------------------------------
There was a file name collision extracting the executable.
See https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo#executable-collision
-----------------------------------------------------


    at de.flapdoodle.embed.process.runtime.Starter.prepare(Starter.java:64)
    at de.flapdoodle.embed.process.runtime.Starter.prepare(Starter.java:45)
    at org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration.embeddedMongoServer(EmbeddedMongoAutoConfiguration.java:113)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 162 more
Caused by: de.flapdoodle.embed.process.extract.ExecutableFileAlreadyExistsException: de.flapdoodle.embed.process.io.file.FileAlreadyExistsException: could not create: /home/circleci/.embedmongo/extracted/Linux-B64--3.5.5/extractmongod
    at de.flapdoodle.embed.process.extract.FilesToExtract$Match.write(FilesToExtract.java:125)
    at de.flapdoodle.embed.process.extract.AbstractExtractor.extract(AbstractExtractor.java:75)
    at de.flapdoodle.embed.process.store.ArtifactStore.extractFileSet(ArtifactStore.java:79)
    at de.flapdoodle.embed.process.store.ExtractedArtifactStore.extractFileSet(ExtractedArtifactStore.java:103)
    at de.flapdoodle.embed.process.runtime.Starter.prepare(Starter.java:53)
    ... 169 more
Caused by: de.flapdoodle.embed.process.io.file.FileAlreadyExistsException: could not create: /home/circleci/.embedmongo/extracted/Linux-B64--3.5.5/extractmongod
    at de.flapdoodle.embed.process.io.file.Files.createTempFile(Files.java:72)
    at de.flapdoodle.embed.process.extract.FilesToExtract$Match.write(FilesToExtract.java:123)
    ... 173 more

(2.3.4.RELEASE BUT nothing relevant should have changed in the newest version I read the code)

So I think it works the following way: - Tests are executed in parallel - Embedded Mongo is downloaded by two modules in parallel - Embedded Mongo(the downloaded file) is extracted BUT the other module was quicker than us face a problem there cause the file already exists - FileAlreadyExistsException

de.flapdoodle.embed.mongo.config.Defaults::extractedArtifactStoreFor which is used by EmbeddedMongoAutoConfiguration defines the file name the thing is extracted to:

executableNaming(new NoopTempNaming())

The NoopTempNaming just chooses a static file name. Which make conflicts happen in case you run the whole thing with multiple modules.

What I wish for

https://github.com/spring-projects/spring-boot/blob/fb8c8afc85098c429996a94652dcdaec79ee812d/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java#L221

Maybe here:

return Defaults.extractedArtifactStoreFor(Command.MongoD)
                    .withExtraction(DirectoryAndExecutableNaming.builder()
                            .directory(new UserHome(".embedmongo/extracted"))
                            .executableNaming(new UUIDTempNaming())
                            .build())
                    .withDownloadConfig(downloadConfig);

or maybe just a better way to customize this than registering a custom RuntimeConfig :thinking: (But then maybe a note in the docs about it, don't know but this just took a quite some time to understand, would not wish that to others)

Other options

  • Flapdoodle could change the Default to make the file name including UUID...
  • Flapdoodle could handle the conflict by just stop extracting and take the file as is BUT making sure it is the right version etc. would be hard to check that deep down in IO logic

Thank you for looking into the issue. :heart:

Comment From: 1-alex98

Sadly my approach to use the UUIDTempNaming leads to new problems

Comment From: 1-alex98

Maybe that is rather an issue for flapdoodle then :thinking:

Comment From: 1-alex98

Workaround: caching the folder the files are extracted to

Comment From: snicoll

@1-alex98 thanks for the report but I am not sure there's much Spring Boot can do about this. Creating a project with a UUID is not great as it will extract to a difference location every time you run the test. I'd rather explore option to fix that in Flapdoodle first. Can you please report that to Flapdoodle? We can reopen if something needs to be tuned in Spring Boot.