Skip to content

Conversation

@christophstrobl
Copy link
Member

ℹ️ Requires: MongoDB Server 3.7.9 ℹ️


MongoDB Transactions

As of version 4, MongoDB will support Transactions. Transactions are built on top of Sessions and therefore require an active ClientSession.

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

To get full programmatic control over transactions, you may want to use the session callback on MongoOperations.

An example of programmatic transaction control within a SessionCallback is shown below:

Programmatic transactions

ClientSession session = client.startSession(options); template.withSession(session) .execute(action -> { session.startTransaction(); try { Step step = // ...; action.insert(step); process(step); action.update(Step.class).apply(Update.set("state", // ... session.commitTransaction(); } catch (RuntimeException e) { session.abortTransaction(); } }, ClientSession::close) .subscribe();

The above example allows you to have full control over transactional behavior while using the session scoped MongoOperations instance within the callback to ensure the session is passed on to every server call.
To avoid some of the overhead that comes with this approach usage of a TransactionTemplate can take away some of the noise of manual transaction flow.

Transactions with TransactionTemplate

template.setSessionSynchronization(ANY); // ... TransactionTemplate txTemplate = new TransactionTemplate(anyTxManager); txTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { Step step = // ...; template.insert(step); process(step); template.update(Step.class).apply(Update.set("state", // ...	}; });

Transactions with MongoTransactionManager

MongoTransactionManager is the gateway to the well known Spring transaction support. It allows applications to use managed transaction features of Spring.
The MongoTransactionManager binds a ClientSession to the thread. MongoTemplate detects those and operates on these resources which are associated with the transaction accordingly. MongoTemplate can also participate in other, ongoing transactions.

@Configuration static class Config extends AbstractMongoConfiguration { @Bean MongoTransactionManager transactionManager(MongoDbFactory dbFactory) { return new MongoTransactionManager(dbFactory);	} // ... } @Component public class StateService { @Transactional void someBusinessFunction(Step step) { template.insert(step); process(step); template.update(Step.class).apply(Update.set("state", // ...	}; });

⚠️ @Transactional(readOnly = true) advises MongoTransactionManager also to start a transaction adding theClientSession to outgoing requests.

Copy link
Member

@mp911de mp911de left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we should also provide a TransactionAwareMongoDbFactoryProxy. This could allow in-flight MongoTemplate creation that can participate in transactions if one is active.

// check for native MongoDB transaction
if (resourceHolder != null && (resourceHolder.hasSession() || resourceHolder.isSynchronizedWithTransaction())) {

resourceHolder.requested();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RefCount is incremented on each access. I think we should increment this one only on first access. Otherwise, multiple calls will reference the underlying resource multiple times without reducing refcount.

* @author Christoph Strobl
* @since 2.1
*/
public enum SessionSynchronization {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NATIVE and ANY are hard to guess names. How about ALWAYS, ON_ACTUAL_TRANSACTION and NEVER (to omit transactional participation even if a Tx is active)?

@juergenzimmermann
Copy link

@christophstrobl Which artifact (and repo) is necessary to try you transactional implementation?

@christophstrobl
Copy link
Member Author

@juergenzimmermann

<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>2.1.0.DATAMONGO-1920-SNAPSHOT</version> </dependency>

via

<repositories> <repository> <id>spring-libs-snapshot</id> <url>https://repo.spring.io/libs-snapshot</url> </repository> </repositories>
MongoTransactionManager is the gateway to the well known Spring transaction support. It allows applications to use managed transaction features of Spring. The MongoTransactionManager binds a ClientSession to the thread. MongoTemplate automatically detects those and operates on them accordingly. static class Config extends AbstractMongoConfiguration {	// ... @bean	MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {	return new MongoTransactionManager(dbFactory);	} } @component public class StateService { @transactional	void someBusinessFunction(Step step) {	template.insert(step);	process(step);	template.update(Step.class).apply(update.set("state", // ...	}; });
@christophstrobl christophstrobl force-pushed the issue/DATAMONGO-1920 branch from 6d72fdd to e71ee57 Compare May 8, 2018 16:02
Slightly tweak method names. Document MongoDatabaseUtils usage in the context of MongoTransactionManager. Rename SessionSynchronization constants to align with AbstractPlatformTransactionManager. Slightly tweak Javadoc and reference docs for typos.
@mp911de mp911de force-pushed the issue/DATAMONGO-1920 branch 2 times, most recently from 2bfda74 to 1f38afa Compare May 9, 2018 13:34
mp911de added 2 commits May 9, 2018 15:49
We now download and unpack MongoDB directly instead of using TravisCI's outdated MongoDB version.
Remove outdated profiles.
@mp911de mp911de force-pushed the issue/DATAMONGO-1920 branch from e6abe82 to 21919a0 Compare May 9, 2018 13:50
mp911de added a commit that referenced this pull request May 9, 2018
We now download and unpack MongoDB directly instead of using TravisCI's outdated MongoDB version. Original pull request: #554.
mp911de added a commit that referenced this pull request May 9, 2018
Remove outdated profiles. Original pull request: #554.
mp911de pushed a commit that referenced this pull request May 9, 2018
…s driver). MongoTransactionManager is the gateway to the well known Spring transaction support. It allows applications to use managed transaction features of Spring. The MongoTransactionManager binds a ClientSession to the thread. MongoTemplate automatically detects those and operates on them accordingly. static class Config extends AbstractMongoConfiguration {	// ... @bean	MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {	return new MongoTransactionManager(dbFactory);	} } @component public class StateService { @transactional	void someBusinessFunction(Step step) {	template.insert(step);	process(step);	template.update(Step.class).apply(update.set("state", // ...	}; }); Original pull request: #554.
mp911de added a commit that referenced this pull request May 9, 2018
Slightly tweak method names. Document MongoDatabaseUtils usage in the context of MongoTransactionManager. Rename SessionSynchronization constants to align with AbstractPlatformTransactionManager. Slightly tweak Javadoc and reference docs for typos. Original pull request: #554.
mp911de added a commit that referenced this pull request May 9, 2018
We now download and unpack MongoDB directly instead of using TravisCI's outdated MongoDB version. Original pull request: #554.
mp911de added a commit that referenced this pull request May 9, 2018
Remove outdated profiles. Original pull request: #554.
@mp911de
Copy link
Member

mp911de commented May 9, 2018

That's merged and polished now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants