apache / apache/grails-core

Transactions do not flush or commit if any validate() calls return false

Open
#14,545 5 comments 1 reaction 0 assignees View on GitHub
relates-to: gorm
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

A service method marked `@Transactional` does not commit properly if it contains calls to validate() that return false. As far as I can tell (from enabling `logSql: true` in application.yml) this is because it doesn't flush at the end of the transaction as I think it should (with the default hibernate flush mode of COMMIT).

The simple grails application at https://github.com/axemanyo10/failing-transaction-flush-demo demonstrates the issue. It has one test that fails - I believe it should pass. Any of the following changes to the application will make the test pass:

1. amend CommentService.groovy and change line 12 from `comment.save()` to `comment.save(flush: true)`
* this is because the application is forcing a flush after every save and not relying on flushing to happen at the end of the transaction
1. amend application.yml and set `hibernate.flush.mode: AUTO`
* same effect as above
1. amend CommentService.groovy - at the end of the `addComments()` method add the line `Comment.withSession { session -> session.flush() }`
* this will force a flush at the end of the transaction - which is what `@Transactional` with flush mode COMMIT is supposed to do
1. amend domain class Comment.groovy and comment out or remove the `static mapping = {...}` block
* this changes the id generation strategy which results in hibernate doing a flush after every call to `save()` rather than waiting until the end of the transaction to flush

None of these changes should affect the service method's transactional behaviour, but they do, and that's why I think this might be a bug.

*Relevant classes*

* [Comment.groovy](https://github.com/axemanyo10/failing-transaction-flush-demo/blob/master/grails-app/domain/failing/transaction/flush/demo/Comment.groovy) (the domain class)
* [CommentService.groovy](https://github.com/axemanyo10/failing-transaction-flush-demo/blob/master/grails-app/services/failing/transaction/flush/demo/CommentService.groovy) (the service)
* [CommentServiceSpec.groovy](https://github.com/axemanyo10/failing-transaction-flush-demo/blob/master/src/test/groovy/failing/transaction/flush/demo/CommentServiceSpec.groovy) (the test)

### Task List

- [x] Steps to reproduce provided
- [x] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)

### Steps to Reproduce

1. checkout example repo @ https://github.com/axemanyo10/failing-transaction-flush-demo
2. gradlew test
3. test fails

### Expected Behaviour

Test should pass

### Actual Behaviour

Test fails

### Environment Information

- **Operating System**: Windows 10
- **GORM Version:** 6.1.10
- **Grails Version (if using Grails):** 3.3.8
- **JDK Version:** 1.8

### Example Application

- https://github.com/axemanyo10/failing-transaction-flush-demo

Contributor guide

Open the contributing guide

Research direction

Start with the failing transaction flush demo and run gradlew test to reproduce the failure. Read Comment.groovy, CommentService.groovy, and CommentServiceSpec.groovy, then compare the listed flush and mapping changes. Done means the existing test passes without changing the service's transactional behavior.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.