grails-data-mapping icon indicating copy to clipboard operation
grails-data-mapping copied to clipboard

withNewSession can cause 'Active connection is required' exception under particular scenarios

Open davidbairdala opened this issue 5 years ago • 3 comments

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

  1. git clone clone https://github.com/davidbairdala/active-connection-required-grails-bug.git
  2. cd to 'active-connection-required-grails-bug'
  3. grails run-app
  4. Click on the links to demonstrate the failure and success scenarios

Expected Behaviour

The links marked as 'Will fail' should succeed without an exception

Actual Behaviour

Links marked as 'Will fail' will throw an exception with the message 'An active connection is required'

It seems that if code inside a withNewSession block calls a method on another service that is marked as Transactional then the exception will occur. It doesn't make any difference if the second service method actually makes use of the database or not.

Stack trace

java.lang.reflect.InvocationTargetException: null
        at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Active Connection is required
        at org.springframework.util.Assert.notNull(Assert.java:134)
        at org.springframework.jdbc.datasource.ConnectionHolder.getConnection(ConnectionHolder.java:150)
        at org.grails.orm.hibernate.GrailsHibernateTemplate.executeWithNewSession(GrailsHibernateTemplate.java:173)
        at org.grails.orm.hibernate.AbstractHibernateDatastore.withNewSession(AbstractHibernateDatastore.java:360)
        at org.grails.orm.hibernate.AbstractHibernateGormStaticApi.withNewSession(AbstractHibernateGormStaticApi.groovy:60)
        at org.grails.datastore.gorm.GormEntity$Trait$Helper.withNewSession(GormEntity.groovy:1025)
        at no.active.connection.TestService.$tt__createFail1(TestService.groovy:14)
        at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
        at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
        at no.active.connection.TestController.$tt__willFail1(TestController.groovy:15)
        at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
        at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
        ... 14 common frames omitted

Environment Information

  • Operating System: Linux (Ubuntu 18.04), Mac OS X
  • GORM Version: 6.1.11-RELEASE
  • Grails Version (if using Grails): 3.3.9
  • JDK Version: OpenJDK 1.8.0_191

Example Application

https://github.com/davidbairdala/active-connection-required-grails-bug.git

davidbairdala avatar Mar 06 '19 00:03 davidbairdala

Anyone aware of a work around?

jacobmarcus avatar Nov 04 '19 14:11 jacobmarcus

+1

We have the same problem with Grails 4.0.0.

In our case the problem only exists, when we use chained afterInsert methods.

Domainclass A has afterInsert that creates eight domainclasses of B and saves them (all in a service). Domainclass B has afterInsert that creates one domainclasses of C and saves it (all in a service).

In the afterInsert of A and B we use Domainclass.withNewSession{}.

The Exception is thrown after all service methods are done in the line where in domainclass A the withNewSession code starts.

larsauswsw avatar Jan 09 '20 10:01 larsauswsw

This issue still exists in grails 5.1.1

Domain.withNewSession {
    Domain.get(1)   // load some domain object into the new session.
    service.anyTransactionMethod()  // can do nothing.
}

the service method runs, but an exception is thrown when the newSession ends.

tircnf avatar Jan 11 '22 22:01 tircnf