DEV Community

Pavel
Pavel

Posted on • Updated on • Originally published at pakisan.github.io

Spring Boot 3 with MongoDB transactions

Transactions won't work without next things:

  • replica set

Since transactions are built on concepts of logical sessions they require mechanics (like oplog) which are only available in replica set environment.

You can always convert a standalone to a single noded replica set and transactions will work with this one node.

https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set/

Reference

  • MongoTransactionManager

Unless you specify a MongoTransactionManager within your application context, transaction support is DISABLED. You can use setSessionSynchronization(ALWAYS) to participate in ongoing non-native MongoDB transactions.

Reference

That's main reason why newly created Spring Boot project with MongoDB will fail with next error:

java.lang.IllegalStateException: Failed to retrieve PlatformTransactionManager for @Transactional test:
Enter fullscreen mode Exit fullscreen mode

What to do:

  • Create replica set
  • Configure MongoTransactionManager as PlatformTransactionManager
  • Update application properties
  • Fix DataMongoTest tests

Create replica set

Choose preferred way to create replica set:

Configure PlatformTransactionManager

Register MongoTransactionManager in the application context.

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;

@Configuration
public class MongoClientConfiguration extends AbstractMongoClientConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String databaseName;

    @Bean
    public MongoTransactionManager transactionManager(MongoDatabaseFactory mongoDatabaseFactory) {
        return new MongoTransactionManager(mongoDatabaseFactory);
    }

    @NotNull
    @Override
    protected String getDatabaseName() {
        return databaseName;
    }

}
Enter fullscreen mode Exit fullscreen mode

Update application properties

spring.data.mongodb.replica-set-name=myReplicaSet
Enter fullscreen mode Exit fullscreen mode

Fix DataMongoTest tests

Looks like @DataMongoTest still not activates autoconfiguration for MongoDB transactions.

References:

Proposal to import TransactionAutoConfiguration didn't help me

@ImportAutoConfiguration(TransactionAutoConfiguration.class)
Enter fullscreen mode Exit fullscreen mode

So I decided to replace it with MongoDBConfig import

import app.config.MongoDBConfig;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.Transactional;

@DataMongoTest
@Transactional
@Import(MongoDBConfig.class)
public class MongoTest {

    @Test
    public void testTransaction() {

    }

}
Enter fullscreen mode Exit fullscreen mode

References

Top comments (0)