Quarkus Hibernate ORM fails to pick the default data source when multiple data sources are defined - quarkus

I have a Quarkus application which has a default reactive postgres data source and jdbc db2 data source. I cannot go with reactive db2 data source because of existing open issue (https://github.com/eclipse-vertx/vertx-sql-client/issues/1131).
During application startup Hibernate ORM is not able to pick the default datasource in the application.properties file and throws error
Exception: Model classes are defined for the default persistence unit, but no default datasource was found. The default EntityManagerFactory will not be created. To solve this, configu
re the default datasource. Refer to https://quarkus.io/guides/datasource for guidance.
at io.quarkus.hibernate.orm.deployment.HibernateOrmProcessor.handleHibernateORMWithNoPersistenceXml(HibernateOrmProcessor.java:932)
at io.quarkus.hibernate.orm.deployment.HibernateOrmProcessor.configurationDescriptorBuilding(HibernateOrmProcessor.java:420)
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 io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:882)
at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at java.base/java.lang.Thread.run(Thread.java:833)
at org.jboss.threads.JBossThread.run(JBossThread.java:501)
application.properties
# Postgres reactive datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc=false
quarkus.datasource.reactive.url=***
quarkus.datasource.username=***
quarkus.datasource.password=***
#DB2 Agoral data source
quarkus.datasource.legacy.db-kind=db2
quarkus.datasource.legacy.reactive=false
quarkus.datasource.legacy.jdbc.url=***
quarkus.datasource.legacy.username=***
quarkus.datasource.legacy.password=***
Hibernate ORM Picks the default data source and everything works fine when the application has only the default data source. Please let me know if I am missing any configuration here. THanks.

Related

Cannot execute update in a read only transaction

As a database we use PostgreSQL. Application uses spring libraries, and transaction is managed by spring. Transactional annotation is used correctly, where it is needed as read-only, and where it is used with write abilities. But in logs we occasinally see exception
2020-12-30 11:39:13.513 [jmsContainer-8] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: cannot execute nextval() in a read-only transaction
2020-12-30 11:39:13.515 [jmsContainer-8] ERROR o.s.t.s.TransactionSynchronizationUtils - TransactionSynchronization.afterCompletion threw exception
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not extract ResultSet
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:780)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:758)
at jdk.internal.reflect.GeneratedMethodAccessor2794.invoke(Unknown Source)
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.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:301)
at com.sun.proxy.$Proxy226.persist(Unknown Source)
Connections to PostgreSQL is provided through pg_bouncer, and pool_mode=sesssion, the server_reset_query=DISCARD ALL.
We tried restarting the pg_bouncer, though maybe some connection by default set read-only and being kept alive, but it did not help.
Any thoughts?

Spring boot integration test with multiple data sources getting url cannot be null

Currently, I am working on spring boot application, we are connecting mysql as part of the main database and H2 Db(in memory) as part of integration testing. Now we have requirement to add two more databases, I am connecting multiple data source by providing multiple data sources in application.properties
spring.mys.datasource.url=jdbc:mysql://17.27.24.33:3306/my-db
spring.mys.datasource.username=root
spring.mys.datasource.password=1234
spring.mys.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.teradata.datasource.url=jdbc:mysql://17.27.24.33:3306/mydb
spring.teradata.datasource.username=root
spring.teradata.datasource.password=password
spring.teradata.datasource.driver-class-name=com.mysql.jdbc.Driver
and when we are having single data source I am able to connect to HSQL in memory db as part for test application.properties with profile test
spring.jpa.database: HSQL
spring.jpa.hibernate.ddl-auto=create-drop
spring.profiles.active=test
After adding second data source my integration testing got failed with below error. Basically, we need to implement integration test for both data sources. appreciate any help, thanks.
Our code in the integration test
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = { ServiceConfig.class, JWTProtectedWebSecurity.class })
public abstract class BaseIRTest {
}
See the error below while running the maven test
2017-11-22 12:31:04.479 ERROR 14648 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
java.sql.SQLException: The url cannot be null
at java.sql.DriverManager.getConnection(DriverManager.java:649) ~[na:1.8.0_60]
at java.sql.DriverManager.getConnection(DriverManager.java:208) ~[na:1.8.0_60]
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.11.jar:na]
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.11.jar:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:732) [tomcat-jdbc-8.5.11.jar:na]
at

java.lang.IllegalStateException: Unable to detect database type for Sybase datasource

I am getting the Unable to detect database type for Sybase Datasource configured in my spring boot application.
Spring boot version: 1.5.3
application.properties
spring.datasource.url=jdbc:jtds:sybase://db-server-name:5555/DBNAME
spring.datasource.username=db_user
spring.datasource.password=db_password
spring.datasource.driver-class-name=net.sourceforge.jtds.jdbc.Driver
spring.jpa.database=sybase
spring.jpa.database-platform=org.hibernate.dialect.SybaseDialect
Debug Information:
// line number 75 in AbstractDatabaseInitializer class
String productName = JdbcUtils.commonDatabaseName(JdbcUtils
.extractDatabaseMetaData(this.dataSource, "getDatabaseProductName")
.toString());
// productName is returned as Sybase from JdbcUtils.extractDatabaseMetaData
DatabaseDriver databaseDriver = DatabaseDriver.fromProductName(productName);
// but there is no databaseDriver found and is returned as UNKNOWN.
// There is no Sybase database configured in DatabaseDriver enum
There is no Sybase datasource configured in DatabaseDriver enum. Can you quickly help to fix this issue ?
Error Stack Trace for reference:
Caused by: java.lang.IllegalStateException: Unable to detect database type
at org.springframework.boot.autoconfigure.AbstractDatabaseInitializer.getDatabaseName(AbstractDatabaseInitializer.java:80)
at org.springframework.boot.autoconfigure.batch.BatchDatabaseInitializer.getDatabaseName(BatchDatabaseInitializer.java:54)
at org.springframework.boot.autoconfigure.AbstractDatabaseInitializer.initialize(AbstractDatabaseInitializer.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134)
... 17 common frames omitted
It works for me. Just put this property in application.properties file. I was facing issue with mysql so I passed mysql here if you are using some other database just pass that(for example: schema-sybase.sql)
spring.batch.schema=classpath:org/springframework/batch/core/schema-mysql.sql
It looks like our detection algorithm is broken with MySQL so I've created this issue to double check it.
In the meantime, please specify the path to your initalization script, this will prevent Spring Boot to attempt to auto-detect it.

Spring Data Neo4j - Cross store persistence

I am new to SDN, I am trying to do a cross store persistence with hibernate. The tutorial given in website has examples for the same, I have checked the github ones too. I have two questions
I am unable to do xml configuration as mentioned in the docs or examples. <neo4j:config/> doesn't support entityManagerFactory. My assumption is it creates the default Neo4jConfiguration which doesn't have a setter for entityManagerFactory. The workaround i have found is to define a CrossStoreNeo4jConfiguration bean.
#Bean
public CrossStoreNeo4jConfiguration crossStoreNeo4jConfiguration(){
CrossStoreNeo4jConfiguration configuration = new CrossStoreNeo4jConfiguration();
configuration.setEntityManagerFactory(entityManagerFactory);
configuration.setGraphDatabaseService(graphDatabaseService);
return configuration;
}
How to do this inside<neo4j:config/>
What happens when you refer a Neo4jTemplate to your repository using neo4j-template-ref when you define repositories using neo4j:repositories? what is the purpose?
UDPATE
The reason it was unable to create CrossStoreNeo4jConfiguration with <neo4j:config/> was , i was missing the dependency spring-data-neo4j-cross-store`. But now i get exception on application start up.
Caused by: java.lang.IllegalStateException: Singleton 'nodeEntityStateFactory' isn't currently in creation
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.afterSingletonCreation(DefaultSingletonBeanRegistry.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:239)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:292)
at org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration$$EnhancerByCGLIB$$779c5955.nodeEntityStateFactory(<generated>)
at org.springframework.data.neo4j.config.Neo4jConfiguration.mappingContext(Neo4jConfiguration.java:199)
at org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration$$EnhancerByCGLIB$$779c5955.CGLIB$mappingContext$11(<generated>)
at org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration$$EnhancerByCGLIB$$779c5955$$FastClassByCGLIB$$3134c8a8.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:280)
at org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration$$EnhancerByCGLIB$$779c5955.mappingContext(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:149)
Thanks in advance.
This should work:
<neo4j:config entityManagerFactory="entityManagerFactory"/>
No need to create your custom implementation.
The template passed to the repository config is the one used by its infrastructure. In most cases there is no need to configure something different.

Getting "Session is closed" exception sometimes

I am using Spring + JPA + Hibernate in my project.
The project is structured as below:
- DAO layer - responsible to get data. DAO returns data in form of Model objects.
- Service layer - Calls DAO and processes/transforms the (Model) data in form required by UI.
I am using #Transactional for methods on Service layer.
I am facing problem where sometimes I get "Session is closed" error while reading data from a Lazily loaded collection.
Also I am not facing this problem consistently.
I get this error sometimes while running from TestNG tests and also when the application is deployed as WAR.
I am pasting the exception I get while running the TestNG tests:
org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
at org.hibernate.impl.SessionImpl.getBatcher(SessionImpl.java:305)
at org.hibernate.loader.Loader.doQuery(Loader.java:854)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2037)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3268)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:147)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:1026)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.applications.qi.etplugin.et.model.impl.ETTestCasePackage_$$_javassist_21.getVertical(ETTestCasePackage_$$_javassist_21.java)
at com.applications.qi.etplugin.et.model.impl.ETTestCasePackage.getVertical(ETTestCasePackage.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:197)
at com.applications.qi.etplugin.et.model.impl.ETTestCasePackage_$$_javassist_21.getVertical(ETTestCasePackage_$$_javassist_21.java)
at com.applications.qi.etplugin.et.dao.impl.TestCaseDAOTest.Test2(TestCaseDAOTest.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:182)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:158)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:194)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:695)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:894)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1219)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
This is my first project using Spring / JPA / Hibernate.
I am not able to find out what may be causing this problem?
Also what can be done to resolve this problem?
Please let me if some more information is required.
Any help / pointers are highly appreciated :)
When you are fetching Lazy objects you receives proxy objects instead of real one.
This is probably happened because you are trying to access not initiated Proxy object after your Transaction finished and session closed.
I believe you need to consider on of two options:
Seriously review your Transaction boundaries, and make sure that all your object operation happens inside those transaction boundaries. It will be something like "Open Session In View" design pattern.
Make all your collections EAGER. In that case you will receive a lot of unnecessary database queries.
Hope it helps.

Resources