Spring or hibernation connection leak

I am using spring with hibernate on webapp (hibernate-core-4.3.8.Final and spring 3.2.11.RELEASE). I use hikaricp (v 2.2.5) as a connection pool, which detects a connection leak and prints the stack below. I am using spring declarative transaction demarcation, so I assume that managing and clearing resources is done using spring / hibernate. Therefore, I think that either spring or hibernation is causing a detected connection leak.

In principle, there is a timer that, when launched, calls the spring bean, marked with the @Transactional annotation.

@Transactional public class InvoiceCycleExporter { public runExportInvoiceCycleJob(){ //this method when called is **sometimes** leaking a connection .... } } 

can you help me trace the source of the connection leak.

my appcontext.xml config for datasource, connection pool, entitymanager below

  <bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig"> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <property name="maximumPoolSize" value="${jdbc.maximumPoolSize}"/> <property name="driverClassName" value="org.postgresql.Driver"/> <property name="leakDetectionThreshold" value="${jdbc.leakDetectionThreshold}"/> </bean> <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="shutdown"> <constructor-arg ref="hikariConfig"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="persistenceUnitName" value="velosPU"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/> //more stuff .... </bean> 

stacktrace below:

 2015-01-13 14:25:00.123 [Hikari Housekeeping Timer (pool HikariPool-0)] WARN com.zaxxer.hikari.util.LeakTask - Connection leak detection triggered, stack trace follows java.lang.Exception: null at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:162) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1435) ~[hibernate-core-4.3.8.Final.jar:4.3.8.Final] at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:61) ~[hibernate-entitymanager-4.3.8.Final.jar:4.3.8.Final] at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:70) ~[spring-orm-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:61) ~[spring-orm-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:378) ~[spring-orm-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:372) ~[spring-tx-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417) ~[spring-tx-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255) ~[spring-tx-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) ~[spring-tx-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633) ~[spring-aop-3.2.11.RELEASE.jar:3.2.11.RELEASE] at com.ukfuels.velos.services.bl.internalinterface.impl.bl.invoicing.**InvoiceCycleExporter (this is the spring bean marked with the transactional annotation)**$$EnhancerBySpringCGLIB$$519c078f.runExportInvoiceCycleJob(<generated>) ~[spring-core-3.2.11.RELEASE.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_65] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_65] at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.impl.ProcessorEndpoint$1.process(ProcessorEndpoint.java:71) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:122) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.impl.ProducerCache.doInAsyncProducer(ProducerCache.java:298) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:117) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.interceptor.BacklogTracerInterceptor.process(BacklogTracerInterceptor.java:84) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:91) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:391) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:273) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:46) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.interceptor.DefaultChannel.process(DefaultChannel.java:335) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:46) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:150) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.RouteInflightRepositoryProcessor.processNext(RouteInflightRepositoryProcessor.java:48) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.loadbalancer.QueueLoadBalancer.process(QueueLoadBalancer.java:44) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.processor.loadbalancer.QueueLoadBalancer.process(QueueLoadBalancer.java:71) ~[camel-core-2.11.4.jar:2.11.4] at org.apache.camel.component.quartz.QuartzEndpoint.onJobExecute(QuartzEndpoint.java:113) ~[camel-quartz-2.11.4.jar:2.11.4] at org.apache.camel.component.quartz.CamelJob.execute(CamelJob.java:61) ~[camel-quartz-2.11.4.jar:2.11.4] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) ~[quartz-1.8.6.jar:na] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) ~[quartz-1.8.6.jar:na] **(a timer is triggered)** 
+6
java spring hibernate connection
source share
2 answers

The issue is discussed here as a whole:

https://github.com/brettwooldridge/HikariCP/issues/34

To narrow the task:

  • Try Spring 4 with Hibernate 4
  • Try a different data source to see if the problem persists.
0
source share

here is some information that, in my opinion, may be useful for debugging connection leaks in general

  • Fix false alarms. For example, if you have a transaction that can potentially run for 5 minutes (for example, when creating a large report) and you set your parameter "leakDetectionThreshold" (or any equivalent for your chosen pool implementation) to 4 minutes, then any transaction, taking more than 4 minutes will be reported as a leak, even if it may not be a real leak (a transaction can completely elegantly and adequately release all connections after 5 minutes).
  • If you use a connection pool, but find that you end up sometimes , think about how you configure your pool. In my case, I configured the pool with "maximumPoolSize" = 100. Hikari will automatically set the configuration to "minimumIdle" (the minimum number of idle connections that HikariCP tries to maintain in the pool) to the same values ​​as "maximumPoolSize", so when you start the pool will be initialized with all 100 connections. But this will mean that when "maxLifetime" (the maximum lifetime of a connection in the pool), then all connections must be updated at the same time . This temporarily reduces the available steep connections. In my magazines, I sometimes saw the following lines.

    HikariPool-0 (total = 100, inUse = 0, avail = 100, wait = 0)
    HikariPool-0 (total = 4, inUse = 0, avail = 4, wait = 0)
    HikariPool-0 (total = 100, inUse = 0, avail = 100, wait = 0)

    the second line, in which the available connections fell to 4, is when the "maximum lifetime" is reached, and the connections need to be updated. Therefore, when setting up the pool, do this so that the connections expire at different times. In my case, I just changed the "minimumIdle" to 40, which means that as the load on the server increases, new connections will gradually (see if your impl pool offers the equivalent of the minToAcquire property), and therefore these connections will have different expiration dates actions.

  • Your connection "maxLifetime" should be less than what your database assigns / waits for the connection so that you do not fall into invalid connections in the pool. UPDATE: some databases may slow down the connection after a certain period of time. For example, postgres has the options 'connectionTimeout' and 'socketTimeout'. So in your application connection pool you do not want to maintain connections longer than this db-force connection timeout, because otherwise you will support an invalid connection / connection already dropped.

+9
source share

All Articles