grails-core: Grails 4: Flush causes TransactionRequiredException: no transaction is in progress

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Clone example repository
  2. Run grails run-app

Expected Behaviour

Console outputs the localhost:8080 url and the app was successfully started.

Actual Behaviour

During startup, the following exception appears:

Configuring Spring Security Core ...
... finished configuring Spring Security Core

2019-07-21 13:58:58.574 ERROR --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

javax.persistence.TransactionRequiredException: no transaction is in progress
        at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3586)
        at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1447)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1443)
        at org.hibernate.Session$flush.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
        at myapp.BootStrap$_closure1$_closure3.doCall(BootStrap.groovy:13)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
        at groovy.lang.Closure.call(Closure.java:405)
        at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
        at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:122)
        at com.sun.proxy.$Proxy132.doInHibernate(Unknown Source)
        at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:297)
        at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:241)
        at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:120)
        at org.grails.orm.hibernate.AbstractHibernateDatastore.withSession(AbstractHibernateDatastore.java:355)
        at org.grails.orm.hibernate.AbstractHibernateGormStaticApi.withSession(AbstractHibernateGormStaticApi.groovy:88)
        at org.grails.datastore.gorm.GormEntity$Trait$Helper.withSession(GormEntity.groovy:917)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
        at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1470)
        at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:985)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:180)
        at myapp.UserRole.withSession(UserRole.groovy)
        at myapp.UserRole$withSession$0.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)
        at myapp.BootStrap$_closure1.doCall(BootStrap.groovy:12)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1099)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
        at groovy.lang.Closure.call(Closure.java:405)
        at groovy.lang.Closure.call(Closure.java:399)
        at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:541)
        at grails.util.Environment.executeForEnvironment(Environment.java:534)
        at grails.util.Environment.executeForCurrentEnvironment(Environment.java:510)
        at org.grails.web.servlet.boostrap.DefaultGrailsBootstrapClass.callInit(DefaultGrailsBootstrapClass.java:74)
        at org.grails.web.servlet.context.GrailsConfigUtils.executeGrailsBootstraps(GrailsConfigUtils.java:83)
        at org.grails.plugins.web.servlet.context.BootStrapClassRunner.onStartup(BootStrapClassRunner.groovy:56)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:269)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:97)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:458)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:445)
        at myapp.Application.main(Application.groovy:11)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

(BootStrap.groovy:13) is the following:

UserRole.withSession {
            it.flush() // line 13
            it.clear()
}

Environment Information

  • Operating System: macOS 10.14.5
  • Grails Version: 4.0.0
  • JDK Version: 11.0.3

Example Application

https://github.com/martinfrancois/grails-4-security-hello-world The steps I did to set it up:

  1. Download basic Grails 4 projects from the forge
  2. Add grails-spring-security
  3. Run s2-quickstart script
  4. Add the code from here: https://grails-plugins.github.io/grails-spring-security-core/snapshot/index.html#5-edit-grails-app-init-bootstrap-groovy-to-add-a-test-user to the Bootstrap file.

Note: this previously worked fine with Grails 3.3.9

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 4
  • Comments: 19 (6 by maintainers)

Most upvoted comments

Just found the solution: Since Hibernate 5.2, flushing outside of transactions is not allowed anymore, see: https://github.com/hibernate/hibernate-orm/blob/5.2/migration-guide.adoc#misc The workaround for this would be to set the following flag in the application.yml file, to restore the previous behavior:

hibernate:
    allow_update_outside_transaction: true

But the “cleaner” way would be to solve the problem at the core, i.e. add transactions to all operations that flush or perform actions like deletions. In the case as described in the issue above, the following works:

UserRole.withTransaction { status ->
    UserRole.withSession {
        it.flush()
        it.clear()
    }
}

If the operation that flushes is in a regular method, you can also annotate the method with @Transactional (this seems not to work in the Bootstrap file and in in static methods, per my testing).

Maybe this is something we should add to the Grails 4 migration guide and maybe also the grails-spring-security documentation?

Just reporting my experience today. Grails 4.0.2 app. Added a method to an existing service. Service has @transactional. New method wouldn’t correctly load, modify or save domain objects. adding save flush reveals the TransactionRequiredException exception. I’m still debugging this, but it seems related.

@pmcneil Hi, what you’re describing seems like a behaviour of @Transactional annotation at class level - as I recall, the handler will apply transactions only to non-javabean methods. So saving in a setXXX will fail unless you apply @Transactional directly to that method. Is that your case?

I thought I posted an issue for that, because that was so not clear from the docs, but cannot find it for reference… bah, i need vacation…

The first issue you should probably set the flush mode to manual with grails.gorm.flushMode="MANUAL" in config.

The latter stack trace is unrelated, but if you can provide an example that reproduces we can certainly take a look.