Posted on • Edited on • Originally published atpakisan.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/
- MongoTransactionManager
Unless you specify a
MongoTransactionManager
within your application context, transaction support is DISABLED. You can usesetSessionSynchronization(ALWAYS)
to participate in ongoing non-native MongoDB transactions.
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:
What to do:
- Create replica set
- Configure
MongoTransactionManager
asPlatformTransactionManager
- Update application properties
- Fix DataMongoTest tests
Create replica set
Choose preferred way to create replica set:
- Docker single node replica set
- Docker multiple node replica set
- Docker compose single node replica set
Configure PlatformTransactionManager
RegisterMongoTransactionManager
in the application context.
importorg.jetbrains.annotations.NotNull;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.mongodb.MongoDatabaseFactory;importorg.springframework.data.mongodb.MongoTransactionManager;importorg.springframework.data.mongodb.config.AbstractMongoClientConfiguration;@ConfigurationpublicclassMongoClientConfigurationextendsAbstractMongoClientConfiguration{@Value("${spring.data.mongodb.database}")privateStringdatabaseName;@BeanpublicMongoTransactionManagertransactionManager(MongoDatabaseFactorymongoDatabaseFactory){returnnewMongoTransactionManager(mongoDatabaseFactory);}@NotNull@OverrideprotectedStringgetDatabaseName(){returndatabaseName;}}
Update application properties
spring.data.mongodb.replica-set-name=myReplicaSet
Fix DataMongoTest tests
Looks like@DataMongoTest
still not activates autoconfiguration for MongoDB transactions.
References:
Proposal to importTransactionAutoConfiguration
didn't help me
@ImportAutoConfiguration(TransactionAutoConfiguration.class)
So I decided to replace it with MongoDBConfig import
importapp.config.MongoDBConfig;importorg.junit.jupiter.api.Test;importorg.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;importorg.springframework.context.annotation.Import;importorg.springframework.transaction.annotation.Transactional;@DataMongoTest@Transactional@Import(MongoDBConfig.class)publicclassMongoTest{@TestpublicvoidtestTransaction(){}}
References
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse