Post

MongoDB transactions with Spring Boot 3

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:

1
java.lang.IllegalStateException: Failed to retrieve PlatformTransactionManager for @Transactional test:

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
    }

}

Update application properties

1
spring.data.mongodb.replica-set-name=myReplicaSet

Fix DataMongoTest tests

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

References:

Proposal to import TransactionAutoConfiguration didn’t help me

1
@ImportAutoConfiguration(TransactionAutoConfiguration.class)

So I decided to replace it with MongoDBConfig import

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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() {

    }

}

References

This post is licensed under CC BY 4.0 by the author.