Unable to access TransactionManager or UserTransaction after updating to Hibernate 5 - java

I just updated from Hibernate 4.2.19 to Hibernate 5.1.2. Of course, little it is to say that things are not going as planned. After solving several issues (among which JOIN FETCH had to be replaced by JOIN), I now run into the next issue:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'idolConfig': Invocation of init method failed; nested exception is org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1575)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
[...]
Caused by: org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.makePhysicalTransactionDelegate(JtaTransactionCoordinatorImpl.java:229)
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.getTransactionDriverControl(JtaTransactionCoordinatorImpl.java:203)
at org.hibernate.engine.transaction.internal.TransactionImpl.<init>(TransactionImpl.java:36)
at org.hibernate.internal.AbstractSessionImpl.getTransaction(AbstractSessionImpl.java:313)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:281)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1326)
at org.hibernate.jpa.internal.EntityManagerImpl.internalGetSession(EntityManagerImpl.java:133)
[...]
The logs show that the JtaPlatform could not be loaded:
2016-11-14 15:34:22,853 DEBUG .o.j.EntityManagerFactoryUtils - Line {272} Opening JPA EntityManager
2016-11-14 15:34:22,973 DEBUG e.t.j.p.i.JtaPlatformInitiator - Line {42} No JtaPlatform was specified, checking resolver
2016-11-14 15:34:22,973 DEBUG e.t.j.p.i.JtaPlatformInitiator - Line {42} No JtaPlatform was specified, checking resolver
2016-11-14 15:34:22,974 DEBUG i.JtaPlatformResolverInitiator - Line {33} No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
2016-11-14 15:34:22,974 DEBUG i.JtaPlatformResolverInitiator - Line {33} No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
2016-11-14 15:34:22,992 DEBUG .i.StandardJtaPlatformResolver - Line {101} Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2016-11-14 15:34:22,992 DEBUG .i.StandardJtaPlatformResolver - Line {101} Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2016-11-14 15:34:22,994 DEBUG .JtaTransactionCoordinatorImpl - Line {258} JtaPlatform#retrieveTransactionManager returned null
2016-11-14 15:34:22,994 DEBUG .JtaTransactionCoordinatorImpl - Line {258} JtaPlatform#retrieveTransactionManager returned null
2016-11-14 15:34:22,995 DEBUG .JtaTransactionCoordinatorImpl - Line {223} Unable to access TransactionManager, attempting to use UserTransaction instead
2016-11-14 15:34:22,995 DEBUG .JtaTransactionCoordinatorImpl - Line {223} Unable to access TransactionManager, attempting to use UserTransaction instead
2016-11-14 15:34:22,995 DEBUG .JtaTransactionCoordinatorImpl - Line {241} JtaPlatform#retrieveUserTransaction returned null
2016-11-14 15:34:22,995 DEBUG .JtaTransactionCoordinatorImpl - Line {241} JtaPlatform#retrieveUserTransaction returned null
I do not have a persistence.xml file. Here is my spring.xml:
<bean id="entityManagerFactoryEcli"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="commonUnit" />
<property name="dataSource" ref="dataSourceEcli" />
<property name="packagesToScan"
value="org.my.common.portal.domain,eu.cec.justice.common.domain.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="javax.persistence.transactionType">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WeblogicTransactionManagerLookup</prop>
<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.JTASessionContext</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.my.common.util.ECLICommonEhCacheRegionFactory</prop>
</props>
</property>
</bean>
<bean id="entityManagerFactoryCommon"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="portalUnit" />
<property name="dataSource" ref="dataSourceCommon" />
<property name="packagesToScan"
value="eu.cec.justice.common.domain.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="javax.persistence.transactionType">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WeblogicTransactionManagerLookup</prop>
<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.JTASessionContext</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.my.common.util.ECLICommonEhCacheRegionFactory</prop>
<prop key="hibernate.ejb.cfgfile">hibernate.cfg.xml</prop>
</props>
</property>
</bean>
<bean id="dataSourceCommon" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="$${portal.common.database.jndi}" />
<property name="resourceRef" value="true" />
</bean>
<bean id="dataSourceEcli" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="$${ecli.database.jndi}" />
<property name="resourceRef" value="true" />
</bean>
<tx:jta-transaction-manager />
<tx:annotation-driven/>
EDIT:
Adding the following to the bean properties did not solve my issue (I also downgraded to Hibernate 5.0.0 but still the problem persists):
<prop key="hibernate.transaction.coordinator_class">org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl</prop>
This also didn't work:
<prop key="hibernate.transaction.coordinator_class">jta</prop>
This also deleting
<prop key="javax.persistence.transactionType">jta</prop>
but this failed as well.

As explained in the User Guide:
Hibernate tries to discover the JtaPlatform it should use through the
use of another service named
org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformResolver.
If that resolution does not work, or if you wish to provide a custom
implementation you will need to specify the
hibernate.transaction.jta.platform setting.
Try providing the underlying JTA platform via the hibernate.transaction.jta.platform configuration property.

Three days of work to find out the solution. Added the following line to spring.xml:
<prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform</prop>
Hibernate 4.x was somehow able to identify that automatically, but now you have to tell it manually which JtaPlatform you are using.

Related

Spring Data JPA Additional EntityManagerFactory Optimized for Cache and Bulk Operations Only

I have a legacy Spring Data JPA application that has a large number of Entities and CrudRepositories. JPA is configured using the XML below. We have a new requirement that requires us to insert 10,000 - 50,000 entities into the database at once via a FileUpload. With the existing configuration the database CPU spikes. After enabling hibernate statistics, its was apparent that these 10,000 insert operations were generating over 200,000 DB queries due to all the validation logic required with a single insert in the InvoiceService.
Original Configuration
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.jdbcurl}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="maxTotal" value="${db.maxTotal}"/>
<property name="maxIdle" value="${db.maxIdle}"/>
<property name="minIdle" value="${db.minIdle}"/>
<property name="initialSize" value="${db.initialSize}"/>
<property name="maxWaitMillis" value="${db.maxWaitMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"/>
<property name="timeBetweenEvictionRunsMillis" value="${db.timeBetweenEvictionRunsMillis}"/>
<property name="testOnBorrow" value="${db.testOnBorrow}"/>
<property name="testOnReturn" value="${db.testOnReturn}"/>
<property name="testWhileIdle" value="${db.testWhileIdle}"/>
<property name="removeAbandonedOnBorrow" value="${db.removeAbandonedOnBorrow}"/>
<property name="removeAbandonedOnMaintenance" value="${db.removeAbandonedOnMaintenance}"/>
<property name="removeAbandonedTimeout" value="${db.removeAbandonedTimeout}"/>
<property name="logAbandoned" value="${db.logAbandoned}"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="flyway">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="my.package.domain" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto:validate}</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
</props>
</property>
<property name="persistenceUnitName" value="entityManagerFactory" />
</bean>
<bean id="persistenceAnnotationBeanPostProcessor" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="defaultPersistenceUnitName" value="entityManagerFactory"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven proxy-target-class="true" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<jpa:repositories base-package="my.package.repository" entity-manager-factory-ref="entityManagerFactory"/>
The FileUploadService snippet looks like this...
EntityManager batchEntityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = batchEntityManager.getTransaction();
transaction.begin();
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
buffer.lines()
.filter(StringUtils::isNotBlank)
.forEach(csvLine -> {
invoiceService.createInvoice(csvLine);
if (counter.incrementAndGet() % (updateFrequency.equals(0) ? 1 : updateFrequency) == 0) {
FileUpload fileUpload1 = fileUploadRepository.findOne(fileUpload.getId());
fileUpload1.setNumberOfSentRecords(sentCount.get());
fileUploadRepository.save(fileUpload1);
transaction.commit();
transaction.begin();
batchEntityManager.clear();
}
});
transaction.commit();
} catch (IOException ex) {
systemException.incrementAndGet();
log.error("Unexpected error while performing send task.", ex);
transaction.rollback();
}
// Update FileUpload status.
FileUpload fileUpload1 = fileUploadRepository.findOne(fileUpload.getId());
fileUpload1.setNumberOfSentRecords(sentCount.get());
if (systemException.get() != 0) {
fileUpload1.setStatus(FileUploadStatus.SYSTEM_ERROR);
} else {
fileUpload1.setStatus(FileUploadStatus.SENT);
}
fileUploadRepository.save(fileUpload1);
batchEntityManager.close();
Most of the DB queries were select statements that return the same results for each record being inserted. It was obvious that enabling EhCache as a Second-Level cache would have a significant performance improvement. However, this application has been running flawlessly in production for several years without ehcache enabled. I am hesitant to turn this on globally as I do not know how this will affect the large number of other repositories/queries.
Question 1
Is there a way to configure a "alternate" EntityManagerFactory that uses the second level cache for this batch process only? How can I choose to use this factory instead of the primary for this batch process only?
I experimented adding something like below to my spring config. I can easily inject this additional EntityManager into my class and use it. However, the existing Repositories (such as FileUploadRepository) don't seem to use it - they just return null. I am not sure if this approach is possible. The documentation for JpaTransactionManager says
This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access
which is exactly what I am not doing. So what other options are there?
<bean id="batchEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="flyway">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="my.package.domain" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto:validate}</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics:false}</prop>
<prop key="hibernate.ejb.interceptor">my.package.HibernateStatistics</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="hibernate.jdbc.batch_size">100</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
</props>
</property>
<property name="persistenceUnitName" value="entityManagerFactory" />
</bean>
Question 2
Assuming there is no other option to "selectively" use EhCache, I tried enabling it on the primary EntityManagerFactory only. We can certainly do regression testing to make sure we don't introduce new issues. I assume this is fairly safe to do? However, another issue came up. I am trying to commit inserts in batches as described in this post and shown in my code above. I am getting an RollbackException when trying to commit the batch due to Connection org.postgresql.jdbc.PgConnection#1e7eb804 is closed.. I presume this is due to the maxWaitMillis property on the dataSource.
I don't want to change this property for every other existing spring Service/Repository/query in the application. If I could use the "custom" EntityManagerFactory I could easily provide a different DataSource Bean with the properties I want. Again, is this possible?
Maybe I looking at this problem all wrong. Are there any other suggestions?
You can have another EntityManagerFactory bean with a different qualifier, so that's one option. I would still recommend you look into these select queries. I bet the problem is just a missing index which causes the database to do full table scans. If you add the proper indexes, you probably don't need to change a thing in your application.

Invalid property 'url' of bean class [com.zaxxer.hikari.HikariConfig]

I am new to spring framework. I am creating a connection pool using Hikari in spring MVC(version 4) + hibernate (version 4) framework application. I am getting the below error while running my application.
Invalid property 'url' of bean class [com.zaxxer.hikari.HikariConfig]: Bean property 'url' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
dispatcher-servelt.xml:
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig" />
</bean>
<!-- HikariConfig config that is fed to above dataSource -->
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="driverClassName" value="${postgres.driver}" />
<property name="url" value="${postgres.url}?stringtype=unspecified" />
<property name="username" value="${postgres.user}" />
<property name="password" value="${postgres.password}" />
<property name="maximumPoolSize" value="${hikari.maximumPoolSize}" />
<property name="idleTimeout" value="30000" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<array>
<value>XXXX</value>
<value>XXXX</value>
</array>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</prop>
<prop key="hibernate.dialect">${postgres.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.jdbc.batch_versioned_data">true</prop>
</props>
</property>
</bean>
hibernate.properties file:
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create/update
hibernate.connection.provider_class=com.zaxxer.hikari.hibernate.HikariConnectionProvider
hibernate.hikari.minimumIdle=5
hibernate.hikari.maximumPoolSize=10
hibernate.hikari.idleTimeout=25200
hibernate.hikari.connectionTimeout=25200
hibernate.hikari.dataSourceClassName=org.postgresql.Driver
hibernate.hikari.dataSource.url=XXXX
hibernate.hikari.dataSource.user=XXXX
hibernate.hikari.dataSource.password=XXXX
hibernate.CharSet=true
hibernate.characterEncoding=true
hibernate.useUnicode=true
pom.xml:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
java version: 8, tomcat: 8.5

Spring test properties file overriden by main properties file

I have a project where I am setting up Spring test configuration, for the DAO (JPA) layer. My test config gets loaded but only after the main config, especially properties file. So instead of trying to connect to HSQLDB, my test connects to the "real" PostGre database.
Here is my test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"/spring-dao-test.xml"})
#Transactional
#Rollback
public class EnseigneDaoTest {
#Autowired
EnseigneDao enseigneDao;
public EnseigneDaoTest() {
// TODO Auto-generated constructor stub
}
#Test
public void testFindById() {
Enseigne enseigne = enseigneDao.findById(Enseigne.class, "4");
assertNotNull(enseigne);
assertEquals("Auchan should have ID 4", "Auchan", enseigne.getLibelle());
}
}
Here is the spring-dao-test.xml :
<!-- Searches for entities in this package, no need for Persistence.xml -->
<context:component-scan base-package="fr.xxx.ddc.dao" />
<context:property-placeholder
location="classpath:fr/insee/config/ddc-dao-test.properties"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="fr.xxx.ddc.model" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaDialect" ref="jpaDialect" />
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${fr.xxx.ddc.hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.max_fetch_depth">${fr.xxx.ddc.hibernate.max_fetch_depth}</prop>
<prop key="hibernate.default_batch_fetch_size">${fr.xxx.ddc.hibernate.default_batch_fetch_size}</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL"/>
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${fr.xxx.database.ddc.driverClassName}"/>
<property name="url" value="${fr.xxx.database.ddc.url}" />
<property name="username" value="${fr.xxx.database.ddc.username}" />
<property name="password" value="${fr.xxx.database.ddc.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
The ddc-dao-test.properties :
fr.xxx.ddc.hibernate.schema=ddc
fr.xxx.ddc.hibernate.max_fetch_depth=3
fr.xxx.ddc.hibernate.default_batch_fetch_size=15
fr.xxx.ddc.hibernate.hbm2ddl.auto=create
fr.xxx.ddc.hibernate.show_sql=false
#Driver H2 pour test
fr.xxx.database.ddc.driverClassName=org.hsqldb.Driver
fr.xxx.database.ddc.url=hsqldb:mem:
fr.xxx.database.ddc.username=sa
fr.xxx.database.ddc.password=
and I get the following log :
09:24:40.262 [main] DEBUG org.springframework.core.env.StandardEnvironment - Adding [class path resource [fr/insee/config/ddc-dao.properties]] PropertySource with lowest search precedence
[...]
09:24:41.717 [main] INFO org.springframework.context.support.PropertySourcesPlaceholderConfigurer - Loading properties file from class path resource [fr/insee/config/ddc-dao-test.properties]
09:24:41.718 [main] DEBUG org.springframework.core.env.MutablePropertySources - Adding [localProperties] PropertySource with lowest search precedence
09:24:41.719 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Searching for key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [environmentProperties]
09:24:41.719 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Searching for key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [systemProperties]
09:24:41.720 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Searching for key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [systemEnvironment]
09:24:41.720 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Searching for key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [class path resource [fr/insee/config/ddc-dao.properties]]
09:24:41.720 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [class path resource [fr/insee/config/ddc-dao.properties]] with type [String] and value '3'
09:24:41.721 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'fr.xxx.ddc.hibernate.max_fetch_depth' in [environmentProperties] with type [String] and value '3'
How do I get rid of the ddc-dao.properties ? It seems there are some concepts I didn't get.
Thanks in advance.
Thanks a lot.
Finally I managed to do it.
The problem is indeed the
<context:component-scan base-package="fr.xxx.ddc.dao" />
loading DaoConfiguration.java, itself loading the main .properties file.
I needed to exclude the class, which is done this way :
<context:component-scan base-package="fr.xxx.ddc.dao" >
<context:exclude-filter type="assignable" expression="fr.xxx.ddc.dao.config.DaoConfiguration"/>
</context:component-scan>
and then my DaoConfiguration is no more loaded, nor the ddc-dao-config.xml or the ddc-dao.properties. My in-memory db is used as the log shows :
org.h2.jdbc.JdbcSQLException: Table "ENSEIGNES" not found
Hope this helps someone.

Spring / Hibernate application hangs during initialization

The web application deploys in other systems. but, it just hangs in my system.
Java Version: jdk1.8
TomcatVersion: apache-tomcat-7.0.63
Spring Version:4.1.6.RELEASE
Hibernate Version:4.3.5.Final
MySQL connector:5.0.8.bin jar
Please see the logs below.
Logs
[org.hibernate.dialect.Dialect] : [MySQL5] -> [org.hibernate.dialect.MySQL5Dialect] (replacing [org.hibernate.dialect.MySQL5Dialect])
[2014-01-14 13:44:25,537 main] [org.hibernate.boot.registry.selector.internal.StrategySelectorImpl : 79] [DEBUG] Registering named strategy selector [org.hibernate.dialect.Dialect] : [MySQL5InnoDB] -> [org.hibernate.dialect.MySQL5InnoDBDialect] (replacing [org.hibernate.dialect.MySQL5InnoDBDialect])
[2014-01-14 13:44:25,609 main] [org.hibernate.cfg.Configuration : 1841] [DEBUG] Preparing to build session factory with filters : {}
[2014-01-14 13:44:25,611 main] [org.hibernate.cfg.Configuration : 1841] [DEBUG] Preparing to build session factory with filters : {}
The deployment just hangs like a sleeping thread after this line. What might the problem? Please let me know if you need more information
EDIT 1 :
I have configured the hibernate sessionfactory via Spring dependency injection. Please check below
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mobile_recharge"/>
<property name="username" value="keerthi" />
<property name="password" value="keerthi" />
<property name="maxIdle" value="-1"></property>
<property name="maxActive" value="-1"></property>
<property name="maxOpenPreparedStatements" value="-1"></property>
<property name="maxWait" value="30000"></property>
<property name="validationQuery" value="SELECT 1"></property>
<property name="testOnBorrow" value="true"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.ciar.mobilerecharge.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="use_sql_comments">true</prop>
</props>
</property>
</bean>

How to configure C3P0 or BoneCP Datasources to withstand database failover/outage

I have a Spring/Hibernate based application which I need to modify to withstand a database outage up to 1 minute.
Instead of writing my own hack I took a look at C3P0 and BoneCP datasources to see if they could be configured for this purpose.
Unfortunently I was not able to get this to work for either of the datasources.
My test program terminated with various exceptions depending on which datasource was used:
With the c3p0 datasource
9558 [main] ERROR org.hibernate.util.JDBCExceptionReporter - connection exception: connection failure: java.net.SocketException: Broken pipe
Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: could not inspect JDBC autocommit mode; nested exception is org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode
With the c3p0 connectionprovider
9341 [main] ERROR org.hibernate.util.JDBCExceptionReporter - connection exception: connection failure: java.io.EOFException
Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: Cannot open connection; nested exception is org.hibernate.exception.JDBCConnectionException: Cannot open connection
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:627)
With the BoneCP datasource
12250 [main] ERROR org.hibernate.util.JDBCExceptionReporter - connection exception: connection failure: java.net.SocketException: Broken pipe
Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: could not inspect JDBC autocommit mode; nested exception is org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:627)
With the BoneCP connectionprovider
19356 [main] ERROR org.hibernate.util.JDBCExceptionReporter - connection exception: connection failure: java.io.EOFException
Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: Cannot open connection; nested exception is org.hibernate.exception.JDBCConnectionException: Cannot open connection
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:627)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:921)
at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:913)
at my.db.failover.CustomerDao.list(CustomerDao.java:14)
The C3P0 documentation states that it can handle a situation like this while the BoneCP documentation don't mention this directly.
To test this I wrote a little program which reads a table from a HSQLDB server and sleeps for a second before repeating the process again.
It can be configured to run with following configurations:
c3p0_datasource.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.hsqldb.jdbcDriver" />
<property name="jdbcUrl" value="jdbc:hsqldb:hsql://localhost:9002" />
<property name="user" value="sa" />
<property name="password" value="" />
<property name="acquireIncrement" value="2" />
<property name="minPoolSize" value="3" />
<property name="maxPoolSize" value="25" />
<property name="idleConnectionTestPeriod" value="3000" />
<property name="acquireRetryAttempts" value="30" />
<property name="acquireRetryDelay" value="1001" />
<property name="breakAfterAcquireFailure" value="false" />
<property name="maxIdleTime" value="0" />
<property name="maxConnectionAge" value="0" />
<property name="maxIdleTimeExcessConnections" value="0" />
<property name="automaticTestTable" value="C3P0_TEST" />
</bean>
<bean id="sessionFactory" parent="abstractSessionFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
c3p0_connectionprovider.xml
<bean id="sessionFactory" parent="abstractSessionFactory">
<property name="hibernateProperties">
<props>
. . .
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.c3p0.acquire_increment">2</prop>
<prop key="hibernate.c3p0.idle_test_period">300</prop>
<prop key="hibernate.c3p0.timeout">1800</prop>
<prop key="hibernate.c3p0.max_size">25</prop>
<prop key="hibernate.c3p0.min_size">1</prop>
<prop key="hibernate.c3p0.max_statement">0</prop>
<prop key="hibernate.c3p0.preferredTestQuery">select 1;</prop>
<prop key="hibernate.c3p0.validate">true</prop>
</props>
</property>
</bean>
bonecp_datasource.xml
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="org.hsqldb.jdbcDriver" />
<property name="jdbcUrl" value="jdbc:hsqldb:hsql://localhost:9002" />
<property name="username" value="sa"/>
<property name="password" value=""/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
<bean id="sessionFactory" parent="abstractSessionFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
bonecp_connectionprovider.xml
<bean id="sessionFactory" parent="abstractSessionFactory">
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.provider_class">com.jolbox.bonecp.provider.BoneCPConnectionProvider</prop>
. . .
<prop key="bonecp.idleMaxAgeInMinutes">2</prop>
<prop key="bonecp.idleConnectionTestPeriodInMinutes">3</prop>
<prop key="bonecp.partitionCount">3</prop>
<prop key="bonecp.acquireIncrement">10</prop>
<prop key="bonecp.maxConnectionsPerPartition">60</prop>
<prop key="bonecp.minConnectionsPerPartition">20</prop>
<prop key="bonecp.statementsCacheSize">50</prop>
<prop key="bonecp.releaseHelperThreads">3</prop>
</props>
</property>
</bean>
Does anyone know if this could be done?
PS!
You can download the test project from this link if anyone needs to look deeper into this :)
Here are the steps to build and run the stuff.
1. Build the project with Maven:
mvn clean install package appassembler:assemble
2. Set the start scripts as executable (Unix/linux)
chmod +x target/appassembler/bin/*
3. Run the DBServer
target/appassembler/bin/dbServer
4. Run the test client from another shell
target/appassembler/bin/client
5. Select one of following configurations to use for the client
0 : c3p0_datasource.xml
1 : c3p0_connectionprovider.xml
2 : bonecp_datasource.xml
3 : bonecp_connectionprovider.xml
6. Terminate the dbServer with ctrl c
7. Start it again and the client should survive the DB outage
But it does not :(
c3p0 will recover from a database outage of arbitrary duration, as long as breakOnAcquireFailure is not set to true. however, that does not mean that clients will never see an Exception on acquire failure. by default, c3p0 will throw Exceptions to clients after a full round of acquisition attempts has failed, which will take 30030 ms (~30 secs) under your config. if you want c3p0 to continue trying to acquire Connections for longer before throwing Exceptions to clients, either set acquireRetryAttempts higher or acquireRetryDelay longer. the total length of a round of acquisition attempts is acquireRetryAttempts * acquireRetryDelay
if you want clients to wait indefinitely for recovery upon a database outage, set acquireRetryAttempts to 0. with this setting, when c3p0 cannot acquire a Connection, it will keep trying indefinitely every acquireRetryDelay milliseconds, and let clients hang until it succeeds or the sun burns out.
Please see http://www.mchange.com/projects/c3p0/#configuring_recovery
p.s. the Exceptions you are providing are very superficial. you'll need to look into log files to see and provide better information about what's going on.

Categories

Resources