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.
Related
I have a remote java client which looks up a JMS connection factory on Wildfly 10, and everything works fine as expected. It is just a test program; a simple JMS chat system. When I start more than one instance of the chat client sometimes the following message appears:
WARN: AMQ212051: Invalid concurrent session usage. Sessions are not supposed to be used by more than one thread concurrently.
Followed by a trace.
Now I want to fix this warning, therefore I need a pooled connection factory. But the pooled connection factory isn't available remotely (and as I read it shouldn't be available remotely).
What can I do to fix this warning when I want to start multiple JMS chat clients locally?
I know that the error won't appear when I just different machines.
This is the working non-pooled remote code (but with warning)
final Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
try {
context = new InitialContext(properties);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
jmsContext = connectionFactory.createContext("quickstartUser", "quickstartPwd1!");
} catch (NamingException e) {
e.printStackTrace();
}
The problem isn't caused by not using a pooled connection factory and won't be solved by using a pooled connection factory. The problem is the way your application is using the same JMS session concurrently between multiple threads (as the WARN message indicates). The stack-trace which is logged will show you which class & method is triggering the WARN message.
You need to ensure that your application does not use the same JMS session concurrently between multiple threads. You can do this by giving each thread its own JMS session or by setting up concurrency controls around the session so that only one thread at a time can access it.
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.
I have created glassfish connection pool with ResourceType as ConnectionPoolDataSource.So, glassfish will use the native connection pool implementation for connection pooling. I am not using XADatasource ResourceType as I don't want to perform any distributed transactions.
My application requires the use of TEMPERORY MYSQL table creation at run time. So I am using
the below code to get the connection from JNDI Datasource of glassfish.
#Resource(mappedName = "jdbc/xxxxx")
private DataSource dataSource;
public Connection getConnection() throws SQLException {
Connection con = dataSource.getConnection();
return con;
}
Now, My question is, Can I perform setAutoCommit(false), commit() and rollback(), close() on this Connection object????
In forum, I read that, we should not call these methods on Connection object, if we get the Connection from Container Managed Distributed Transaction (XADataSource) as its involved in distributed transactions.
But, I am getting this connection from non-distributed transactions.So, I can call those methods right???
Other question is, after performing db operations, If I call con.close(), will this connection go back to the connection pool again?
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.
Is it possible to set the Oracle connection cache to restart cached connections after a period of time?
You can use the new Universal Connection Pool. The class oracle.ucp.jdbc.PoolDataSource has apropriate methods.
e.g.
void setTimeToLiveConnectionTimeout(int timeToLiveConnectionTimeout)
throws java.sql.SQLException
see javadoc at: http://download.oracle.com/docs/cd/B28359_01/java.111/e11990/oracle/ucp/jdbc/PoolDataSource.html