diff --git a/app/server/appsmith-server/pom.xml b/app/server/appsmith-server/pom.xml
index e8dde563432f..5b55099f6730 100644
--- a/app/server/appsmith-server/pom.xml
+++ b/app/server/appsmith-server/pom.xml
@@ -16,6 +16,7 @@
This is the API server for the Appsmith project
+ 4.33.0
1.35
2.4.4
@@ -173,13 +174,13 @@
de.flapdoodle.embed
de.flapdoodle.embed.mongo
- 4.12.0
+ ${flapdoodle.version}
test
de.flapdoodle.embed
- de.flapdoodle.embed.mongo.spring30x
- 4.11.0
+ de.flapdoodle.embed.mongo.spring3x
+ ${flapdoodle.version}
test
diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java
new file mode 100644
index 000000000000..0a7905283893
--- /dev/null
+++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoPackageTest.java
@@ -0,0 +1,71 @@
+package com.appsmith.server.configurations;
+
+import de.flapdoodle.embed.mongo.packageresolver.Command;
+import de.flapdoodle.embed.mongo.packageresolver.PlatformPackageResolver;
+import de.flapdoodle.embed.process.distribution.Distribution;
+import de.flapdoodle.embed.process.distribution.Version;
+import de.flapdoodle.os.CommonArchitecture;
+import de.flapdoodle.os.CommonOS;
+import de.flapdoodle.os.ImmutablePlatform;
+import de.flapdoodle.os.Platform;
+import de.flapdoodle.os.linux.LinuxDistribution;
+import de.flapdoodle.os.linux.UbuntuVersion;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+
+import java.io.IOException;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class EmbeddedMongoPackageTest {
+
+ @ParameterizedTest
+ @MethodSource("platforms")
+ void configuredVersion_resolvesNativePackage(Platform platform, String archivePrefix) throws IOException {
+ String version = PropertiesLoaderUtils.loadProperties(new ClassPathResource("application-test.properties"))
+ .getProperty("de.flapdoodle.mongodb.embedded.version");
+
+ String url = new PlatformPackageResolver(Command.MongoD)
+ .packageFor(Distribution.of(Version.of(version), platform))
+ .url();
+
+ assertThat(url).startsWith(archivePrefix + version + ".");
+ }
+
+ private static Stream platforms() {
+ return Stream.of(
+ Arguments.of(
+ ImmutablePlatform.builder()
+ .operatingSystem(CommonOS.OS_X)
+ .architecture(CommonArchitecture.ARM_64)
+ .build(),
+ "/osx/mongodb-macos-arm64-"),
+ Arguments.of(
+ ImmutablePlatform.builder()
+ .operatingSystem(CommonOS.OS_X)
+ .architecture(CommonArchitecture.X86_64)
+ .build(),
+ "/osx/mongodb-macos-x86_64-"),
+ Arguments.of(ubuntu(CommonArchitecture.X86_64), "/linux/mongodb-linux-x86_64-ubuntu2204-"),
+ Arguments.of(ubuntu(CommonArchitecture.ARM_64), "/linux/mongodb-linux-aarch64-ubuntu2204-"),
+ Arguments.of(
+ ImmutablePlatform.builder()
+ .operatingSystem(CommonOS.Windows)
+ .architecture(CommonArchitecture.X86_64)
+ .build(),
+ "/windows/mongodb-windows-x86_64-"));
+ }
+
+ private static Platform ubuntu(CommonArchitecture architecture) {
+ return ImmutablePlatform.builder()
+ .operatingSystem(CommonOS.Linux)
+ .architecture(architecture)
+ .distribution(LinuxDistribution.Ubuntu)
+ .version(UbuntuVersion.Ubuntu_22_04)
+ .build();
+ }
+}
diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java
new file mode 100644
index 000000000000..fff5235e33f2
--- /dev/null
+++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/EmbeddedMongoTest.java
@@ -0,0 +1,98 @@
+package com.appsmith.server.configurations;
+
+import com.mongodb.reactivestreams.client.ClientSession;
+import com.mongodb.reactivestreams.client.MongoClient;
+import com.mongodb.reactivestreams.client.MongoCollection;
+import de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration;
+import org.bson.Document;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+import java.util.Locale;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringJUnitConfig(EmbeddedMongoTest.MongoTestConfig.class)
+@TestPropertySource(locations = "classpath:application-test.properties")
+class EmbeddedMongoTest {
+
+ private static final Duration TIMEOUT = Duration.ofSeconds(15);
+
+ @Autowired
+ private MongoClient mongoClient;
+
+ @Value("${de.flapdoodle.mongodb.embedded.version}")
+ private String configuredVersion;
+
+ @Test
+ void configuredVersion_runsNativelyWithReplicaSet() {
+ Document buildInfo = Mono.from(mongoClient.getDatabase("admin").runCommand(new Document("buildInfo", 1)))
+ .block(TIMEOUT);
+ assertThat(buildInfo).isNotNull();
+ assertThat(buildInfo.getString("version")).isEqualTo(configuredVersion);
+
+ String architecture = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
+ String mongoArchitecture =
+ buildInfo.get("buildEnvironment", Document.class).getString("target_arch");
+ if (architecture.equals("aarch64") || architecture.equals("arm64")) {
+ assertThat(mongoArchitecture).isIn("aarch64", "arm64");
+ } else if (architecture.equals("amd64") || architecture.equals("x86_64")) {
+ assertThat(mongoArchitecture).isIn("x86_64", "amd64");
+ } else {
+ assertThat(mongoArchitecture).isEqualTo(architecture);
+ }
+
+ Document hello = Mono.from(mongoClient.getDatabase("admin").runCommand(new Document("hello", 1)))
+ .block(TIMEOUT);
+ assertThat(hello).containsEntry("setName", "appsmith-replica-set").containsEntry("isWritablePrimary", true);
+ }
+
+ @Test
+ void replicaSet_supportsTransactionCommitAndAbort() {
+ MongoCollection collection =
+ mongoClient.getDatabase("embedded_mongo_smoke").getCollection("transactions");
+ Mono.from(collection.insertOne(new Document("_id", "existing"))).block(TIMEOUT);
+ try (ClientSession session = Mono.from(mongoClient.startSession()).block(TIMEOUT)) {
+ assertThat(session).isNotNull();
+ assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(1);
+
+ session.startTransaction();
+ Mono.from(collection.insertOne(session, new Document("_id", "committed")))
+ .block(TIMEOUT);
+ Mono.from(session.commitTransaction()).block(TIMEOUT);
+ assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(2);
+
+ session.startTransaction();
+ Mono.from(collection.insertOne(session, new Document("_id", "aborted")))
+ .block(TIMEOUT);
+ assertThat(Mono.from(collection.countDocuments(session)).block(TIMEOUT))
+ .isEqualTo(3);
+ Mono.from(session.abortTransaction()).block(TIMEOUT);
+ assertThat(Mono.from(collection.countDocuments()).block(TIMEOUT)).isEqualTo(2);
+ assertThat(Mono.from(collection.find(new Document("_id", "aborted")).first())
+ .block(TIMEOUT))
+ .isNull();
+ } finally {
+ Mono.from(collection.drop()).block(TIMEOUT);
+ }
+ }
+
+ @TestConfiguration(proxyBeanMethods = false)
+ @Import(TransactionalConfig.class)
+ @ImportAutoConfiguration({
+ EmbeddedMongoAutoConfiguration.class,
+ MongoAutoConfiguration.class,
+ MongoReactiveAutoConfiguration.class
+ })
+ static class MongoTestConfig {}
+}
diff --git a/app/server/appsmith-server/src/test/resources/application-test.properties b/app/server/appsmith-server/src/test/resources/application-test.properties
index 324efe64371f..c674b235c076 100644
--- a/app/server/appsmith-server/src/test/resources/application-test.properties
+++ b/app/server/appsmith-server/src/test/resources/application-test.properties
@@ -1,5 +1,5 @@
-# embedded mongo DB version which is used during junit tests
-de.flapdoodle.mongodb.embedded.version=5.0.5
+# Embedded MongoDB for JUnit tests; Flapdoodle selects the native OS/CPU build.
+de.flapdoodle.mongodb.embedded.version=7.0.34
logging.level.root=error
appsmith.git.root = /dev/shm/git-storage
diff --git a/contributions/ServerSetup.md b/contributions/ServerSetup.md
index 54dcdcd7c9ae..7966c5a1a70d 100644
--- a/contributions/ServerSetup.md
+++ b/contributions/ServerSetup.md
@@ -437,6 +437,23 @@ mvn -B clean compile && ./build.sh -DskipTests
```
## Running Tests on Server
+MongoDB-backed JUnit tests use an isolated replica set started by Flapdoodle. The
+MongoDB version is pinned in
+`app/server/appsmith-server/src/test/resources/application-test.properties`.
+Flapdoodle downloads the build for the operating system and CPU architecture and
+caches it under `~/.embedmongo`. A separately installed MongoDB is not required for
+these tests. On Apple Silicon, use an ARM64 JDK; `mvn -v` should report `aarch64` or
+`arm64` as the architecture.
+
+To check native MongoDB startup, platform package selection, and transaction
+commit/rollback without starting Redis, run from `app/server`:
+
+```bash
+mvn -pl appsmith-server -am test \
+ -Dtest=EmbeddedMongoPackageTest,EmbeddedMongoTest \
+ -Dsurefire.failIfNoSpecifiedTests=false
+```
+
1. Ensure that you have Redis running on your local system.
2. Run the command to execute tests from repo root: