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
- Clone example repository
- 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:
- Download basic Grails 4 projects from the forge
- Add grails-spring-security
- Run s2-quickstart script
- 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
Bootstrapfile.
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)
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.ymlfile, to restore the previous behavior: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:
If the operation that flushes is in a regular method, you can also annotate the method with
@Transactional(this seems not to work in theBootstrapfile 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-securitydocumentation?@pmcneil Hi, what you’re describing seems like a behaviour of
@Transactionalannotation at class level - as I recall, the handler will apply transactions only to non-javabean methods. So saving in asetXXXwill fail unless you apply@Transactionaldirectly 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.