apache / apache/grails-core

Nested transactions doesn't work

Open
#14,391 1 comment 2 reactions 0 assignees View on GitHub
relates-to: grails-data-mongodb
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

I'm using Grails 4.0.2 and Gorm 7.0.3. Mongo DB is configured with codec engine.
I work in a start-up that intensively use Grails with MongoDB. We are now building an architecture based on plugins and each of our APIs often requires many database writes on multiple collections. We want to achieve code consolidation by using transactions, in order to support rollback of all writes in the case of unpredictable exception throws.

We found that methods marked with @Transactional annotation works as expected: each save() inside the method is committed at the method end, and if an exception occurs nothing is effectively written to db.

Problems starts when using nested @Transactional methods: the child method is always executed in a new transaction, and all the save() calls in the child method are committed at its method end. If an exception is thrown in the parent method after calling the child method, all the data inside the child method are already committed to database.

I've done a lot of debugging and i found that Gorm for MongoDB is using a transaction manager called **"DatastoreTransactionManager"** that extends "AbstractPlatformTransactionManager", and it has a property "nestedTransactionAllowed" that is set by default to "false". I've also set this property to "true" in my "doWithApplicationContext" method, but the behaviour remains the same.

I found that the engine that is intended to check if a transaction already exist, in order to join in it, make use of the method **"isExistingTransaction"** that is declared in "AbstractPlatformTransactionManager" and **return always "false".** This method is not overrided in "DatastoreTransactionManager. After seeing that i thought that Gorm for MongoDB version 7.0.2 simply does not support nested transactions. I think this demonstrates the problem i found.

I've also checked the library "spring-data-mongodb" that has the class "MongoTransactionManager" that extends "AbstractPlatformTransactionManager" and correctly implements implemented "isExistingTransaction" method. I've tried to replace the Gorm "DatastoreTransactionManager" bean with the "MongoTransactionManager" bean in "spring-data-mongodb" library, but after spending a lot of time and facing out a lot of errors and incompatibilities i'm enough sure this is not a practicable way.

Please help us to solve this very big problem, as we are building an enterprise class architecture and we are very confortable with Grails up to this.

Thanks a lot

Contributor guide

Open the contributing guide

Research direction

Start by reading Gorm for MongoDB's DatastoreTransactionManager and the AbstractPlatformTransactionManager.isExistingTransaction method described in the issue. Trace how nested @Transactional calls are handled and compare the behavior with Spring Data MongoDB's MongoTransactionManager. Done means nested writes participate in the parent transaction and roll back when the parent fails.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, mongodb, spring
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.