I'm using Grails 6.2.0 tyring to use the ConnectionSources API to add and remove Datasources at runtime, but got a NullPointerException (NPE). If the SAME code is exected during BootStrap it works, but on calling later at runtime via Service it fails
Should add the datasource and the corresponding tenant
Actual Behaviour
Fails with stacktrace
Caused by: java.lang.NullPointerException: Cannot invoke "org.grails.orm.hibernate.cfg.Mapping.getBatchSize()" because "m" is null
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindSubClass(GrailsDomainBinder.java:1508)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindSubClasses(GrailsDomainBinder.java:1467)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindRoot(GrailsDomainBinder.java:1410)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.contribute(GrailsDomainBinder.java:161)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:292)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:86)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:479)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709)
at org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.buildSessionFactory(HibernateMappingContextConfiguration.java:287)
at org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory.create(HibernateConnectionSourceFactory.java:86)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:39)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:23)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.createRuntime(AbstractConnectionSourceFactory.java:70)
at org.grails.datastore.mapping.core.connections.InMemoryConnectionSources.addConnectionSource(InMemoryConnectionSources.groovy:51)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSources.addConnectionSource(AbstractConnectionSources.groovy:96)
Environment Information
Operating System: Windows
GORM Version: Default for Grails 6.2.0
Grails Version (if using Grails): 6.2.0
JDK Version: JDK17
StackTrace during BootStrap > OK
at com.devc.storage.DataSourceManager.addArchiveDataSource(DataSourceManager.groovy:70)
at com.devc.storage.ArchiveService.$tt__init(ArchiveService.groovy:91)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1254)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1030)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:1036)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:1019)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:97)
at com.devc.storage.ArchiveService$_init_closure4.doCall(ArchiveService.groovy)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1030)
at groovy.lang.Closure.call(Closure.java:427)
at groovy.lang.Closure.call(Closure.java:416)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at com.devc.storage.ArchiveService.init(ArchiveService.groovy)
at com.devc.storage.ArchiveService$init.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
at com.devc.BootStrap.initDataSources(BootStrap.groovy:94)
at com.devc.BootStrap$initDataSources$5.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
StackTrace using a service --> FAILS
at com.devc.storage.DataSourceManager.addArchiveDataSource(DataSourceManager.groovy:70)
at com.devc.storage.ArchiveService.$tt__takeOnline(ArchiveService.groovy:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1254)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1030)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:1036)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:1019)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:97)
at com.devc.storage.ArchiveService$_takeOnline_closure2.doCall(ArchiveService.groovy)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1030)
at groovy.lang.Closure.call(Closure.java:427)
at groovy.lang.Closure.call(Closure.java:416)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at com.devc.storage.ArchiveService.takeOnline(ArchiveService.groovy)
at com.devc.storage.ArchiveService$takeOnline$3.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
at com.devc.storage.ArchiveController.takeOnline(ArchiveController.groovy:42)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
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:1072)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
##############
Example code to reproduce: -> HibernateDataStore is set during bootstrap
ConnectionSource addConfigDataSource() {
ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(_CONFIGDBNAME)
if (!s) {
Map<String, Object> dbconfig = getDatabaseConfig(ConstraintService._APPLICATION_NAME + "-" + _CONFIGDBNAME, false)
s = _hibernateDatastore.getConnectionSources().addConnectionSource(
_CONFIGDBNAME,
dbconfig)
log.info "Datasource added for system database" + _CONFIGDBNAME
}
return s
}
Set getConnectionSourceNames() {
Set result = new HashSet()
ConnectionSources<SessionFactory, HibernateConnectionSourceSettings> connectionSources = _hibernateDatastore.getConnectionSources()
for (ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> connectionSource in connectionSources) {
result.add(connectionSource.name)
//println "Name $connectionSource.name -> $connectionSource.source -> $connectionSource.settings"
}
return result
}
ConnectionSource addArchiveDataSource(String archivepath, String archivename) {
ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(archivename)
if (!s) {
Map<String, Object> dbconfig = getDatabaseConfig(archivepath + "/" + archivename + "/archive", true)
s = _hibernateDatastore.getConnectionSources().addConnectionSource(
archivename,
dbconfig)
log.info "Datasource added for archive " + archivename
}
return s
}
void removeArchiveDataSource(String archivename) {
ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(archivename)
if (s) {
if (s == _hibernateDatastore.getConnectionSources().getDefaultConnectionSource()) {
throw new Exception("NOT ALLOWED to close the default connection, stupid!")
}
// Closing connection
s.close()
log.info "Datasource closed for archive " + archivename
}
}
Hi,
I'm using Grails 6.2.0 tyring to use the ConnectionSources API to add and remove Datasources at runtime, but got a NullPointerException (NPE). If the SAME code is exected during BootStrap it works, but on calling later at runtime via Service it fails
hibernateDatastore.getConnectionSources().addConnectionSource( archivename, dbconfig)
Steps to Reproduce
_hibernateDatastore.getConnectionSources().addConnectionSource( archivename, dbconfig)
Expected Behaviour
Should add the datasource and the corresponding tenant
Actual Behaviour
Fails with stacktrace
Caused by: java.lang.NullPointerException: Cannot invoke "org.grails.orm.hibernate.cfg.Mapping.getBatchSize()" because "m" is null at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindSubClass(GrailsDomainBinder.java:1508) at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindSubClasses(GrailsDomainBinder.java:1467) at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindRoot(GrailsDomainBinder.java:1410) at org.grails.orm.hibernate.cfg.GrailsDomainBinder.contribute(GrailsDomainBinder.java:161) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:292) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:86) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:479) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709) at org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.buildSessionFactory(HibernateMappingContextConfiguration.java:287) at org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory.create(HibernateConnectionSourceFactory.java:86) at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:39) at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:23) at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.createRuntime(AbstractConnectionSourceFactory.java:70) at org.grails.datastore.mapping.core.connections.InMemoryConnectionSources.addConnectionSource(InMemoryConnectionSources.groovy:51) at org.grails.datastore.mapping.core.connections.AbstractConnectionSources.addConnectionSource(AbstractConnectionSources.groovy:96)
Environment Information
StackTrace during BootStrap > OK
StackTrace using a service --> FAILS
##############
Example code to reproduce: -> HibernateDataStore is set during bootstrap
package com.devc.storage
import com.devc.ConstraintService import grails.compiler.GrailsCompileStatic import groovy.util.logging.Slf4j import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.mapping.core.connections.ConnectionSources import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings import org.hibernate.SessionFactory import org.springframework.transaction.annotation.Transactional
@GrailsCompileStatic @Slf4j @Singleton class DataSourceManager {
private static String _CONFIGDBNAME = "config" HibernateDatastore _hibernateDatastore
void init(HibernateDatastore hb) { _hibernateDatastore = hb addConfigDataSource() }
private static Map<String, Object> getDatabaseConfig(String dbname, boolean isencrypted) { Map<String, Object> dbconfig = [ "hibernate.hbm2ddl.auto": "update", "dialect" : "org.hibernate.dialect.H2Dialect", "driverClassName" : "org.h2.Driver", "pooled" : "true", "username" : ConstraintService.getProperty('info_app_dbuser'), "password" : ConstraintService.getProperty('info_app_dbpass') + (isencrypted ? " " + ConstraintService.getProperty('info_app_dbpass') : ""), "url" : "jdbc:h2:./" + dbname + ";LOCK_TIMEOUT=10000" + (isencrypted ? ";CIPHER=AES" : "") ] as Map<String, Object> return dbconfig }
HibernateDatastore getDataStore() { return _hibernateDatastore }
ConnectionSource addConfigDataSource() { ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(_CONFIGDBNAME) if (!s) { Map<String, Object> dbconfig = getDatabaseConfig(ConstraintService._APPLICATION_NAME + "-" + _CONFIGDBNAME, false) s = _hibernateDatastore.getConnectionSources().addConnectionSource( _CONFIGDBNAME, dbconfig) log.info "Datasource added for system database" + _CONFIGDBNAME } return s }
Set getConnectionSourceNames() {
Set result = new HashSet()
ConnectionSources<SessionFactory, HibernateConnectionSourceSettings> connectionSources = _hibernateDatastore.getConnectionSources()
for (ConnectionSource<SessionFactory, HibernateConnectionSourceSettings> connectionSource in connectionSources) {
result.add(connectionSource.name)
//println "Name $connectionSource.name -> $connectionSource.source -> $connectionSource.settings"
}
return result
}
ConnectionSource addArchiveDataSource(String archivepath, String archivename) { ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(archivename) if (!s) { Map<String, Object> dbconfig = getDatabaseConfig(archivepath + "/" + archivename + "/archive", true) s = _hibernateDatastore.getConnectionSources().addConnectionSource( archivename, dbconfig) log.info "Datasource added for archive " + archivename } return s }
void removeArchiveDataSource(String archivename) { ConnectionSource s = _hibernateDatastore.getConnectionSources().getConnectionSource(archivename) if (s) { if (s == _hibernateDatastore.getConnectionSources().getDefaultConnectionSource()) { throw new Exception("NOT ALLOWED to close the default connection, stupid!") } // Closing connection s.close() log.info "Datasource closed for archive " + archivename } }
}