homicki opened a new issue, #16571:
URL: https://github.com/apache/grails-core/issues/16571

   ### 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:
   
   ```groovy
   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


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to