Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'HibernateException: No Session found for current thread' for readOnly dataSource #10556

Closed
armsargis opened this issue Mar 30, 2017 · 11 comments

Comments

@armsargis
Copy link

After updating from grails 3.2.7 to grails 3.2.8 I have exception:

org.hibernate.HibernateException: No Session found for current thread
	at org.grails.orm.hibernate.GrailsSessionContext.currentSession(GrailsSessionContext.java:116)
	at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:688)
	at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:173)
	at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:167)
	at grails.gorm.DetachedCriteria$_withPopulatedQuery_closure8.doCall(DetachedCriteria.groovy:742)
	at org.grails.datastore.gorm.GormStaticApi$_withDatastoreSession_closure22.doCall(GormStaticApi.groovy:831)
	at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:319)
	at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:40)
	at org.grails.datastore.gorm.GormStaticApi.withDatastoreSession(GormStaticApi.groovy:830)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.withDatastoreSession(GormEntity.groovy:899)
	at grails.gorm.DetachedCriteria.withPopulatedQuery(DetachedCriteria.groovy:735)
	at grails.gorm.DetachedCriteria.count(DetachedCriteria.groovy:507)
	at grails.gorm.DetachedCriteria.count(DetachedCriteria.groovy:506)
	at com.webbfontaine.grails.plugins.taglibs.BeanDataLoadService.$tt__doLoadData(BeanDataLoadService.groovy:36)
	at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
	at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
	at com.webbfontaine.grails.plugins.taglibs.SimpleTagLib$_closure3.doCall(SimpleTagLib.groovy:115)
	at org.grails.taglib.TagOutput.captureTagOutput(TagOutput.java:64)
	at org.grails.taglib.TagLibraryMetaUtils$_registerMethodMissingForTags_closure3.doCall(TagLibraryMetaUtils.groovy:58)
	at com.webbfontaine.wftaglib.ApplicationOverriddenTagLib$_closure14.doCall(ApplicationOverriddenTagLib.groovy:432)
	at org.grails.gsp.GroovyPage.invokeTagLibClosure(GroovyPage.java:410)
	at org.grails.gsp.GroovyPage.invokeTag(GroovyPage.java:335)
	at home_sargis_projects_grails3_sad_grails_app_views_sad_search__searchCriteria_gsp$_run_closure5.doCall(home_sargis_projects_grails3_sad_grails_app_views_sad_search__searchCriteria_gsp:89)
	at org.grails.taglib.TagBodyClosure.executeClosure(TagBodyClosure.java:200)
	at org.grails.taglib.TagBodyClosure.captureClosureOutput(TagBodyClosure.java:102)
	at org.grails.taglib.TagBodyClosure.call(TagBodyClosure.java:213)
	at com.webbfontaine.grails.plugins.conversation.WfConvFormTagLib$_closure1$_closure2.doCall(WfConvFormTagLib.groovy:30)
	at org.grails.taglib.TagBodyClosure.executeClosure(TagBodyClosure.java:200)
	at org.grails.taglib.TagBodyClosure.captureClosureOutput(TagBodyClosure.java:102)
	at org.grails.taglib.TagBodyClosure.call(TagBodyClosure.java:213)
	at org.grails.plugins.web.taglib.FormTagLib$_closure9.doCall(FormTagLib.groovy:447)
	at org.grails.taglib.TagOutput.captureTagOutput(TagOutput.java:78)
	at org.grails.taglib.TagLibraryMetaUtils$_registerMethodMissingForTags_closure1.doCall(TagLibraryMetaUtils.groovy:48)
	at com.webbfontaine.grails.plugins.conversation.WfConvFormTagLib$_closure1.doCall(WfConvFormTagLib.groovy:35)
	at org.grails.gsp.GroovyPage.invokeTagLibClosure(GroovyPage.java:417)
	at org.grails.gsp.GroovyPage.invokeTag(GroovyPage.java:335)
	at home_sargis_projects_grails3_sad_grails_app_views_sad_search__searchCriteria_gsp.run(home_sargis_projects_grails3_sad_grails_app_views_sad_search__searchCriteria_gsp:290)
	at org.grails.gsp.GroovyPageWritable.doWriteTo(GroovyPageWritable.java:162)
	at org.grails.gsp.GroovyPageWritable.writeTo(GroovyPageWritable.java:82)
	at org.grails.web.gsp.GroovyPagesTemplateRenderer.makeTemplate(GroovyPagesTemplateRenderer.java:232)
	at org.grails.web.gsp.GroovyPagesTemplateRenderer.render(GroovyPagesTemplateRenderer.java:113)
	at org.grails.plugins.web.taglib.RenderTagLib$_closure7.doCall(RenderTagLib.groovy:367)
	at org.grails.gsp.GroovyPage.invokeTagLibClosure(GroovyPage.java:417)
	at org.grails.gsp.GroovyPage.invokeTag(GroovyPage.java:335)
	at home_sargis_projects_grails3_sad_grails_app_views_sad_list_gsp$_run_closure2.doCall(home_sargis_projects_grails3_sad_grails_app_views_sad_list_gsp:77)
	at org.grails.taglib.TagBodyClosure.executeClosure(TagBodyClosure.java:200)
	at org.grails.taglib.TagBodyClosure.captureClosureOutput(TagBodyClosure.java:102)
	at org.grails.taglib.TagBodyClosure.call(TagBodyClosure.java:213)
	at org.grails.plugins.web.taglib.SitemeshTagLib.captureTagContent(SitemeshTagLib.groovy:48)
	at org.grails.plugins.web.taglib.SitemeshTagLib$_closure3.doCall(SitemeshTagLib.groovy:156)
	at org.grails.gsp.GroovyPage.invokeTagLibClosure(GroovyPage.java:417)
	at org.grails.gsp.GroovyPage.invokeTag(GroovyPage.java:335)
	at home_sargis_projects_grails3_sad_grails_app_views_sad_list_gsp.run(home_sargis_projects_grails3_sad_grails_app_views_sad_list_gsp:100)
	at org.grails.gsp.GroovyPageWritable.doWriteTo(GroovyPageWritable.java:162)
	at org.grails.gsp.GroovyPageWritable.writeTo(GroovyPageWritable.java:82)
	at org.grails.web.servlet.view.GroovyPageView.renderTemplate(GroovyPageView.java:76)
	at org.grails.web.servlet.view.AbstractGrailsView.renderWithinGrailsWebRequest(AbstractGrailsView.java:71)
	at org.grails.web.servlet.view.AbstractGrailsView.renderMergedOutputModel(AbstractGrailsView.java:55)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
	at org.grails.web.sitemesh.GrailsLayoutView.renderInnerView(GrailsLayoutView.java:150)
	at org.grails.web.sitemesh.GrailsLayoutView.obtainContent(GrailsLayoutView.java:128)
	at org.grails.web.sitemesh.GrailsLayoutView.renderTemplate(GrailsLayoutView.java:63)
	at org.grails.web.servlet.view.AbstractGrailsView.renderWithinGrailsWebRequest(AbstractGrailsView.java:71)
	at org.grails.web.servlet.view.AbstractGrailsView.renderMergedOutputModel(AbstractGrailsView.java:55)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
	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.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
	at grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter.doFilter(UpdateRequestContextHolderExceptionTranslationFilter.groovy:64)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.groovy:53)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:158)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.groovy:62)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at grails.plugin.springsecurity.web.SecurityRequestHolderFilter.doFilter(SecurityRequestHolderFilter.groovy:58)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
	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:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

and here is service definition:

@Transactional(readOnly = true)
class BeanDataLoadService {

def doLoadData(params) {
......
}

}

service creating DetachedCriteria for one domain class and executed query.

Domain using datasource which is marked as readOnly:

rimm:
        pooled: true
        jmxExport: true
        driverClassName: org.h2.Driver
        readOnly: true
        username: sa
        password:

if I remove readOnly from dataSource definition everything works as before. I guess issue related with commit: f17ad39

Environment Information

  • Operating System: Linux
  • Grails Version: 3.2.8
  • JDK Version: Oracle java version "1.8.0_121"
@armsargis armsargis changed the title 'HibernateException: No Session found for current threadà for readOnly dataSource 'HibernateException: No Session found for current thread' for readOnly dataSource Mar 30, 2017
@graemerocher
Copy link
Member

I suggest you upgrade to GORM 6.1 and use the new grails.gorm.transactions.Transactional annotation instead with the connection name specified:

@Transactional(readOnly = true, connection="rimm")

@armsargis
Copy link
Author

I will update and check. Just one notice our domain classes defined in plugin and in domain classes we defined already our datasource mapping to rimm we should repeat rimm in our services also? Its looks like duplication and and creating coupling also I guess

@graemerocher
Copy link
Member

graemerocher commented Mar 30, 2017

Well what you have now is it creating a transaction for default connection, so your service is not actually binding the correct transaction. The only reason it worked before is because Grails was binding a session (but not creating a transaction) for your secondary data source

@armsargis
Copy link
Author

Thanks for explanation, btw I updated to GORM 6.1.0 and have following exception for some reason its trying to use JPA configuration:

2017-03-30 18:05:16.394 ERROR --- [ost-startStop-1] o.s.b.c.embedded.tomcat.TomcatStarter    : Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'grailsCacheFilter': Cannot create inner bean '(inner bean)#6e2a7b9c' of type [grails.plugin.cache.web.filter.simple.MemoryPageFragmentCachingFilter] while setting bean property 'filter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '(inner bean)#6e2a7b9c': Unsatisfied dependency expressed through method 'setUrlMappingsHandlerMapping' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'urlMappingsHandlerMapping': Unsatisfied dependency expressed through method 'setWebRequestInterceptors' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration$JpaWebMvcConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 21: dataSource_son,dataSourceUnproxied_security,dataSource_scimod,dataSourceUnproxied_so_tables,dataSourceLazy_security,dataSourceUnproxied_scimod,dataSourceLazy_rimm,dataSourceLazy_son,dataSourceUnproxied_rimm,dataSource_so_vws,dataSourceUnproxied_so_vws,dataSourceUnproxied_son,dataSourceLazy_so_vws,dataSource_gim                                                                                                                                                                 ,dataSourceLazy_scimod,dataSourceUnproxied_gim,dataSource_security,dataSourceLazy_so_tables,dataSource_rimm,dataSource_so_tables,dataSourceLazy_gim
2017-03-30 18:05:16.531 ERROR --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a single bean, but 21 were found:
        - dataSource_son: defined in null
        - dataSourceUnproxied_security: defined in null
        - dataSource_scimod: defined in null
        - dataSourceUnproxied_so_tables: defined in null
        - dataSourceLazy_security: defined in null
        - dataSourceUnproxied_scimod: defined in null
        - dataSourceLazy_rimm: defined in null
        - dataSourceLazy_son: defined in null
        - dataSourceUnproxied_rimm: defined in null
        - dataSource_so_vws: defined in null
        - dataSourceUnproxied_so_vws: defined in null
        - dataSourceUnproxied_son: defined in null
        - dataSourceLazy_so_vws: defined in null
        - dataSource_gim: defined in null
        - dataSourceLazy_scimod: defined in null
        - dataSourceUnproxied_gim: defined in null
        - dataSource_security: defined in null
        - dataSourceLazy_so_tables: defined in null
        - dataSource_rimm: defined in null
        - dataSource_so_tables: defined in null
        - dataSourceLazy_gim: defined in null


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

:bootRun FAILED

@graemerocher
Copy link
Member

Interesting, could you provide an example that reproduces? As a workaround please add:

@EnableAutoConfiguration(excludes=[org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration])

To your Application class

@graemerocher graemerocher added this to the grails-3.2.9 milestone Mar 30, 2017
@armsargis
Copy link
Author

Here is another exception after excluding JPA

javax.persistence.TransactionRequiredException: no transaction is in progress
        at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3425)
        at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1396)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1392)
        at org.grails.orm.hibernate5.support.HibernatePersistenceContextInterceptor.flush(HibernatePersistenceContextInterceptor.java:129)
        at org.grails.orm.hibernate.support.AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.flush(AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java:93)
        at org.grails.web.servlet.context.GrailsConfigUtils.executeGrailsBootstraps(GrailsConfigUtils.java:68)
        at org.grails.plugins.web.servlet.context.BootStrapClassRunner.onStartup(BootStrapClassRunner.groovy:53)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:256)
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:882)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:372)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:388)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:375)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.webbfontaine.sad.Application.main(Application.groovy:13)

Will try to create sample project and reproduce issue.

Thanks.

@zyro23
Copy link
Contributor

zyro23 commented Mar 31, 2017

one more question reg. the original issue (readOnly dataSources excluded from ChainedTransactionManager):

what is the recommended pattern for a service that writes to one datasources and reads from other datasources?

  • making sure that a OpenSessionInViewInterceptor/PersistenceContextInterceptor wraps the logic opening sessions for the additional datasources?
  • using withNewSession on the domains of the secondary dataSources manually?
  • pulling out the logic accessing the secondary dataSources into other methods/services using @Transactional(connection = "second")?

personally, i would like to at least have the option to configure the legacy ChainedTransactionManager behavior back.
i.e. opening sessions for readOnly dataSources as well

@graemerocher
Copy link
Member

@armsargis Sounds like you are using Hibernate 5.2, please downgrade to Hibernate 5.1.x until this issue is resolved

@graemerocher
Copy link
Member

@zyro23 The last one, using services to wrap the logic that accessed the second data source.

Note that ChainedTransactionManager will be disabled by default in Grails 3.3 and above with an option to re-enable it. Binding a session for every data source for every transaction is not efficient.

However, we can add an option to re-enable ChainedTransactionManager for readOnly data sources. I will see what we can do about that.

@armsargis
Copy link
Author

Thanks @graemerocher btw I think nice to have option to re-enable it to have a time to organize migration considering that usually usages such code in many plugins and many applications

@graemerocher
Copy link
Member

Looking at the code it seems there is already an option to re-enable by specifying the dataSource as transactional:

rimm:
        pooled: true
        jmxExport: true
        driverClassName: org.h2.Driver
        transactional: true # add this line
        readOnly: true
        username: sa
        password:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants