Issues

Select view

Select search mode

 
50 of 109

ActionQueue.BeforeTransactionCompletionProcessQueue incorrectly throws AssertionFailure wrapping a JPA exception instead of propagating

Description

Since Hibernate 5.2.x native HibernateExceptions are in many cases automatically wrapped in JPA exceptions via AbstractSharedSessionContract#exceptionConverter though not consistently, see https://hibernate.atlassian.net/browse/HHH-12666#icft=HHH-12666

If a HibernateException is thrown in the commit phase, and it is converted to a JPA exception, the following code inActionQueue.BeforeTransactionCompletionProcessQueue does not expect a JPA exception, so it wraps the JPA exception in an AssertionFailure, which is clearly not the intended result:

public void beforeTransactionCompletion() { while ( !processes.isEmpty() ) { try { processes.poll().doBeforeTransactionCompletion( session ); } catch (HibernateException he) { throw he; } catch (Exception e) { throw new AssertionFailure( "Unable to perform beforeTransactionCompletion callback", e ); } } }

This causes any client code which may potentially be expecting to catch either JPA or HibernateExceptions in the commit phase to fail. The solution is propagating JPA exceptions just like HibernateExceptions.

Currently, the workaround is enabling hibernate.native_exception_handling_51_compliance as implemented by https://hibernate.atlassian.net/browse/HHH-12666#icft=HHH-12666 which anyway seems to be preferred overall, since the transition to JPA exception seems to be quite inconsistent, plus client code is still in most cases expecting HibernateExceptions instead of JPA exceptions (the Spring integration in particular deals only with HibernateExceptions in most places, even though some support for JPA exceptions thrown by Hibernate was added in the latest releases).

Created May 1, 2019 at 2:04 PM
Updated December 4, 2019 at 4:45 PM

Activity

Show:

Manuel Dominguez SarmientoMay 1, 2019 at 2:05 PM
Edited

This is a real stack trace we obtained when running into this issue:

org.hibernate.AssertionFailure: Unable to perform beforeTransactionCompletion callback at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:952) at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:521) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2452) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:625) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy158.save(Unknown Source) at com.renxo.cms.integration.CustomerFactoryImpl.getCustomerForSubscriberNumberInternal(CustomerFactoryImpl.java:570) at com.renxo.cms.integration.CustomerFactoryImpl.getCustomerForSubscriberNumber(CustomerFactoryImpl.java:212) at com.renxo.cms.web.struts.action.customer.CustomerAction$BatchBlacklistTask.run(CustomerAction.java:649) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: javax.persistence.PessimisticLockException: could not execute batch at org.hibernate.internal.ExceptionConverterImpl.wrapLockException(ExceptionConverterImpl.java:249) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:103) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1443) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423) at org.hibernate.envers.internal.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:177) at org.hibernate.envers.internal.synchronization.AuditProcessManager$1.doBeforeTransactionCompletion(AuditProcessManager.java:47) at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:946) ... 24 more Caused by: org.hibernate.PessimisticLockException: could not execute batch at com.renxo.cms.dao.hibernate.CustomOracleSQLExceptionConversionDelegate.convert(CustomOracleSQLExceptionConversionDelegate.java:105) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:128) at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:104) at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:147) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:212) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:629) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:474) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1437) ... 28 more Caused by: java.sql.BatchUpdateException: ORA-08177: can't serialize access for this transaction at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:12296) at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:246) at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:128) at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java) at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:118) ... 36 more

Flag notifications