apache / apache/grails-core

Reference to cross-referenced domain objects do not persist outside session

Open
#11,670 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.