Reference to cross-referenced domain objects do not persist outside session
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
### Task List
- [x] Steps to reproduce provided
- [x] Stacktrace (if present) provided
- [x] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)
### Steps to Reproduce
This issue originates from a more complicated issue, I have brought it down to the essence here and created a small demo project.
This used to work in Grails 2.5.1 and does not work in 4.0.4 and 4.0.6.
We have 2 domain classes that can reference each other:
```
class A {
String name
B ref
}
class B {
String name
A ref
}
```
A pair of these can be created like this:
```
A.withTransaction {
def a=new A(name:"A")
def b=new B(name:"B")
a.ref=b
b.ref=a
a.save(failOnError:true)
b.save(failOnError:true)
}
```
The result can be shown as follows:
```
A.findAll().each { a ->
println "a.id: ${a.id} a.name: ${a.name} a.ref.id: ${a.ref?.id} a.ref.name: ${a.ref?.name}"
}
B.findAll().each { b ->
println "b.id: ${b.id} b.name: ${b.name} b.ref.id: ${b.ref?.id} b.ref.name: ${b.ref?.name}"
}
```
Which works in both Grails 2.5.1 and 4.0.4 / 4.0.6 when run from the same session. The result is:
> a.id: 1 a.name: A a.ref.id: 1 a.ref.name: B
> b.id: 1 b.name: B b.ref.id: 1 b.ref.name: A
But when run lateron from a new session, or within a .withNewSession closure in Grails 4.0.4 / 4.0.6 we get:
> a.id: 1 a.name: A a.ref.id: 1 a.ref.name: B
> b.id: 1 b.name: B b.ref.id: null b.ref.name: null
In Grails 2.5.1 we get the same result as from inside the original session.
It seems to depend on the order of the .save statements. When they are reversed b is correct and a is wrong.
### Stacktrace
There is no stacktrace. Application runs without any exceptions thrown.
### Expected Behaviour
The expected behaviour would be that b.ref equals a and is persisted.
### Actual Behaviour
b.ref is null
### Environment Information
- **Operating System**: Ubuntu 20.04
- **Grails Version:** 4.0.4 / 4.0.6
- **JDK Version:** OpenJDK Runtime Environment (build 1.8.0_275-8u275-b01-0ubuntu1~20.04-b01)
- **Container Version (If Applicable):** None
### Example Application
See demo project here: https://github.com/joosth/cross-reference-domain-objects
Fetching http://localhost:8080/demo/create will create the domain objects and list them immediately
Fetching http://localhost:8080/demo/list will list the domain objects and show the missing reference.
Contributor guide
Research direction
Start with the linked demo application's A and B domain classes and reproduce the behavior through the /demo/create and /demo/list endpoints, including a new session. Compare the results with the two save orders and the Grails 4.0.4/4.0.6 environment details. Done means both cross-references load after the session changes, regardless of save order.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100