HibernateOptimisticLockingFailureException marks connection as 'closed'? - spring

I'm getting the following stack trace:
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.btfin.wrapcore.request.MFRequest] with identifier [2850448]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.btfin.wrapcore.request.MFRequest#2850448]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
Which is due to an optimistic locking exception. I can address the root cause of this.
My question is - in this scenario - the exception handling sets the database connection to 'closed'. (Which causes issues with my connection pool).
What is the pattern for handling a database exception like HibernateOptimisticLockingFailureException that bubbles up through spring and hibernate and returns a closed connection?
Do you know the part in the Spring/Hibernate code that sets the connection to closed?

Hibernate Docs clearly state that if any exception occur while working with the Session, the Session can't be reused afterwards. Moreover, each Session can encompass several transactions and after each transaction commits - the same happens, the connection is closed.
But while using a connection pool, the connection is not literally closed, when close() method is invoked, the connection is returned to the pool without physical closing:
when an application closes its connection, the underlying physical
connection is recycled rather than being closed.
So if you have problems with the connection being physically closed, I would rather pay more attention to the pool, not to Hibernate or Spring - they can't do more than invoking close() which should work as I described earlier.

Related

When does JPA return connection to db pool

I have a Restendpoint that makes a database call (jpa) to check the permission and after that an external call is made. The result of this external call is returned to the caller. When the external call takes very long i got the following exception:
java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
25 lines skipped for [org.hibernate]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143)
It seems that jpa keeps the connection of the db pool til the restendpoint returns the response. I would like to force jpa to return the connection after the permission check is done. Is there a way to do this (like a annotation)?
The solution to my problem was to disable spring.jpa.open-in-view. In that case the database connection is imediatly returned to the db pool after jpa has used it. disadvantage is that related data has to be loaded separately.

org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection

I sometimes notice below mentioned error in my springboot app logs.
org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
I suspect it could be because of exception thrown from #Transactional method ( only at times though).
Is it Ok to throw excaption from #Transactional method? or it is a bad practice?
Here is my service layer code
#Override
#Transactional
public void updateMessageStatus(String status, String sid, String errorCode) throws NotFoundException {
OutgoingMessage outgoingMessage = outgoingMessageRepository.findByResourceSid(sid);
if (outgoingMessage == null) {
throw new NotFoundException(ErrorCode.MESSAGE_NOT_FOUND, sid);
}
outgoingMessage.setStatus(status);
outgoingMessage.setUpdatedTime(Calendar.getInstance().getTime());
outgoingMessageRepository.save(outgoingMessage);
}
This usually happens when app is idle for longer time than the server’s connection timeout period.
So if a connection has been idle longer than this timeout value, it will be dropped by the server. By default, Hibernate uses its internal database connection pool library,
keeping the connection open to be reused later.
Hibernate reuses the idle connection which was already dropped by the server, hence we get JDBCConnectionExceptionis error.
What I noticed is even with the following database auto-reconnect setup should not work in this case.
spring.datasource.validation-query=select 1
spring.datasource.testOnBorrow=true
May be need to increase the pool size OR Entity Manager needs to be closed once the transaction is done.
spring.datasource.hikari.maximum-pool-size=10.
Please let me know if this worked for you.

Spring Hibernate Connection from database not released

I am getting the following error below
Unexpected error
org.springframework.transaction.CannotCreateTransactionException:
**CannotCreateTransactionException:** Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBC
Exception: Could not open connection
Here is the scenario in which it occurs :
I have recently moved some table from mysql to mongo. The code is written in such a way that either data would be taken from mongo/mysql.
The code is written in a method block which is annotated with #Transactional provided by spring framework.
There is hibernate layer which is using transaction provided by spring. c3p0 is the connection pool.
The parameter of connection pool is
hibernate.c3p0.min_size=5
hibernate.c3p0.timeout=1200
hibernate.c3p0.max_size=35
hibernate.c3p0.max_statements=50
The problem comes when we try to pull the data from mongo.Looks like the transaction is not getting closed because of mongo operation.The database connection is not getting released .It reaches the max size defined in the pool.
Tried the query in DB to find out the connection
show status like '%onn%';
Any suggestion to resolve this would really help.
Thanks

EJB 3 JDBC Connection Close in Autocommit false

Writing a EJB 3 Service with container managed transaction. If i set autocommit false perform SQL updates and close the JDBC connection within the EJB transaction,will the transaction be still active and commit after the method completes without any exception with the connection currently closed
If you use CMT and connection from the JTA enabled datasource, then when you call connection.close() the connection is not actually closed but returned to the pool. You should also not change the autocommit with the connections taken from such datasource as they are by default set to false and shouldn't be changed. Yes, transaction will still be active, and will be commited/rollbacked, when the transaction scope ends (it doesn't have to be exactly when this particular method completes, since transaction could be started earlier and this method may only participate in it via REQUIRED, instead of running in separate as with REQIRES_NEW.

Glassfish 4.0 serializable coonection pools not working with Oracle XA transactions

I have a problem that I don't know how solve and researching the net has not helped me much. I declare in glassfish 4.0 asadmin console a serializable connection pool and its corresponding resource.
create-jdbc-connection-pool --datasourceclassname oracle.jdbc.xa.client.OracleXADataSource --maxpoolsize 8 --isolationlevel serializable --restype javax.sql.XADataSource --property Password=A_DB:User=A_DB:URL="jdbc\:oracle\:thin\:#localhost\:1521\:orcl" ATestPool
create-jdbc-resource --connectionpoolid ATestPool jdbc/ATest
Then inside a stateless bean I build a datasource via jndi as follows:
InitialContext ic = new InitialContext();
jndiDataSource = (DataSource) ic.lookup("jdbc/ATest");
and I'm getting connection as follows
jndiDataSource.getConnection();
Connections are properly obtained and released via finally clauses in each method we they are needed.
However, pairing serializable connection pool with XA data sources seems not to work, as getting first connections throws the following pair of exceptions in the order shown below
JTS5041: The resource manager is doing work outside a global transaction
oracle.jdbc.xa.OracleXAException
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
RAR5029:Unexpected exception while registering component
javax.transaction.SystemException
at com.sun.jts.jta.TransactionImpl.enlistResource(TransactionImpl.java:224)
with the following
RAR7132: Unable to enlist the resource in transaction. Returned resource to pool. Pool name: [ ATestPool ]]]
RAR5117 : Failed to obtain/create connection from connection pool [ ATestPool ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: javax.transaction.SystemException]]
RAR5114 : Error allocating connection : [Error in allocating a connection. Cause: javax.transaction.SystemException]]].
Now if the connection pool is recreated without --isolationlevel serializable, then application works fine without any changes into the code. Also, if one keeps the isolation parameter and uses non-XA transactions as
--datasourceclassname oracle.jdbc.pool.OracleDataSource
--restype javax.sql.DataSource
then again application works without any changes into the code.
I was wondering if anyone could explain to me what could be wrong in the above setup and how to actually make serializable work with XA data sources. Thanks.
I think you need to enable useNativeXA.

Resources