Skip to content

Implicit transaction wrapping fails with UncategorizedMongoDbException on Standalone MongoDB instances #947

Description

@gwynejsn

Description

When using Flamingock with Spring Boot auto-configuration and Spring Data MongoDB, Flamingock automatically detects transaction capabilities. If there is a PlatformTransactionManager in the context (for example, introduced by spring-modulith-starter-mongodb), Flamingock implicitly wraps migration pipeline executions inside transactional boundaries.

However, when running against a Standalone MongoDB deployment (which does not support replica sets or transactions), this fails with the following exception:

org.springframework.data.mongodb.UncategorizedMongoDbException: This MongoDB deployment does not support retryable writes. Please add retryWrites=false to your connection string.

Adding retryWrites=false or setting flamingock.transaction-enabled=false in the application configuration properties does not resolve this if MongoDBSpringDataTargetSystem is instantiated, because the driver attempts to initialize transactional sessions regardless of those properties.


Steps to Reproduce

  1. Run a local standalone MongoDB instance (no replica set enabled).
  2. Configure a Spring Boot application with both flamingock-mongodb-springdata-targetsystem and spring-modulith-starter-mongodb (which registers a MongoTransactionManager).
  3. Set properties in application.properties:
    flamingock.transaction-enabled=false
    spring.mongodb.uri=mongodb://localhost:27017/db?retryWrites=false
  4. Start the application context and observe the migration runner failure.

Expected Behavior

Setting flamingock.transaction-enabled=false should completely bypass the creation of MongoDBSpringDataTxWrapper (or use a no-op implementation) so that migrations can run successfully on standalone database deployments without attempting transaction sessions.


Current Workaround

Currently, to work around this on a standalone MongoDB instance, developers must override the MongoDBSpringDataTargetSystem bean and inject a custom no-op TransactionWrapper programmatically:

@Bean
public MongoDBSpringDataTargetSystem mongoDBSpringDataTargetSystem(MongoTemplate mongoTemplate) {
    return new MongoDBSpringDataTargetSystem("mongodb-name", mongoTemplate) {
        @Override
        public io.flamingock.internal.core.transaction.TransactionWrapper getTxWrapper() {
            return new io.flamingock.internal.core.transaction.TransactionWrapper() {
                @Override
                public <T> T wrapInTransaction(ExecutionRuntime runtime, Function<ExecutionRuntime, T> function) {
                    return function.apply(runtime); // Bypass transaction creation
                }
            };
        }
    };
}

Environment Info

  • Flamingock Version: 1.4.4
  • Spring Boot Version: 3.x / 4.x
  • MongoDB Driver Version: 5.x
  • MongoDB Server Deployment: Standalone (v6.x / v7.x)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions