DEV Community

Pavel
Pavel

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

6

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

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay