grails-data-hibernate7: request-session connection closes after a lazy load inside withNewSession

Aperta
#16,571 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@borinquenkid ci sta già lavorando.

Dal 26/10/2026.

  • #16763 di @borinquenkid — aperta

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
32/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
groovy, mariadb, mysql
Ambito
database

Direzione di ricerca

The failure sits in the Hibernate session handling of grails-data-hibernate7, around executeWithNewSession and GrailsHibernateTemplate's exception conversion. Start by reproducing with the linked repro app (./gradlew bootRun, then curl /repro) and reading the JDBC log that precedes the NullPointerException. Done means the request session stays usable after withNewSession { withTransaction { ... } } and a regression spec covers the case.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Expected Behavior

In this report, the request session is the Hibernate session that open session in view (OSIV) binds. The new session is the session that withNewSession opens. The inner transaction is the transaction that withTransaction starts in the new session.

After withNewSession { withTransaction { … } } completes, the OSIV-bound request session remains usable. Subsequent queries and refresh() succeed.

Actual Behaviour

Code runs in the request session without a transaction. It runs and ends a transaction on the request session. It then calls withNewSession { withTransaction { } }. Inside that block, it reads a lazy association of an entity that the request session loaded.

After the block, the next statement of the request session fails because its connection is closed. GrailsHibernateTemplate then throws a NullPointerException ("Cannot throw exception because the return value of ... convertHibernateAccessException(...) is null"). Before the NullPointerException, the log shows the JDBC error. On H2, the error is The object is already closed [90007-240].

Steps To Reproduce
  1. Clone https://github.com/homicki/grails8-withnewsession-closed-connection-repro and run ./gradlew bootRun.
  2. curl -i http://localhost:8080/repro returns 500 with the NullPointerException above.
  3. curl -i "http://localhost:8080/repro?lazyLoad=before" returns 200. This control reads the association before the block.

The action runs in the OSIV request session without a transaction. BootStrap seeds one book and its author, and Book.author is lazy:

Book book = Book.first()
Author.withTransaction { Author.count() }      // ends a transaction on the request session

Book.withNewSession {
    Book.withTransaction {
        book.author.name                        // lazy load through the request session
        new Author(name: 'Tenar').save()
    }
}
Book.count()                                    // fails: the connection is closed

The reproduction fails when all three of these conditions are true: a transaction ended on the request session earlier, the first use of the request session after that transaction is inside the inner transaction, and the inner block uses withNewSession. In the tested variants, withNewTransaction alone succeeds, and loading the association before or after the block also succeeds.

Proposed fix: before executeWithNewSession unbinds the request session, make an open, disconnected request session get its own connection. I have this fix with a spec that fails without it and passes with it, written with AI assistance. If the team agrees with this approach, I can submit it as a pull request.

Environment Information
  • Grails 8.0.x
  • Hibernate ORM 7.4
  • Spring Framework 7.0
  • MariaDB 10.11 and MySQL 8.4
  • Groovy 5.1
  • JDK 25
Example Application

https://github.com/homicki/grails8-withnewsession-closed-connection-repro

Version

8.0.0

Lingua principale
Groovy
Stelle
2.9k
Fork
980
Merge medio
1g 17h
PR unite (30g)
192

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/grails-core

Tutte le issue di apache/grails-core

Issue simili

Altre issue su Databases

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.