title: Unknown threading issue causes asynchronous Spring controller method to leak db connections
body: <p>I have a asynchronous Spring MVC controller method (which returns a DeferredResult) that calls a Spring service method that itself use the entityManager in order to retrieve data from a database.</p>
  
  <p>Somehow, <strong>the async controller method causes connections to be leaked/abandoned</strong>. Here is the full stacktrace:</p>
  
  <pre><code>    thread (controller) = http-bio-8080-exec-2
      org.apache.commons.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2013-03-26 15:54:42 by the following code was never closed:
          at org.apache.commons.dbcp.AbandonedTrace.setStackTrace(AbandonedTrace.java:139)
          at org.apache.commons.dbcp.AbandonedObjectPool.borrowObject(AbandonedObjectPool.java:81)
          at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
          at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
          at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:70)
          at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292)
          at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:297)
          at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:169)
          at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67)
          at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
          at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1395)
          at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:59)
          at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:71)
          at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:378)
          at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
          at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
          at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:273)
          at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$before$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
          at com.bignibou.service.MessageServiceImpl.findUnreadMessages(MessageServiceImpl.java:36)
          at com.bignibou.controller.MessageController.getMessages(MessageController.java:87)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:601)
          at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
          at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
          at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
          at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
          at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
          at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
          at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
          at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
          at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
          at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:816)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
          at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
          at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
          at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
          at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
          at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
          at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
          at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
          at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
          at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:180)
          at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
          at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
          at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
          at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(Charact
  thread (service) = http-bio-8080-exec-2
  </code></pre>
  
  <p>I know for certain that the controller and service methods run in the same thread because I have logged it with a <code>Thread.currentThread().getName();</code> call and in the above case the thread is <strong>http-bio-8080-exec-2</strong>.</p>
  
  <p>What I can't pinpoint it the cause of the leak/abandoned connection...</p>
  
  <p>Can anyone please help?</p>
  
  <p><strong>EDIT 1</strong>: Here is the relevant Spring config:</p>
  
  <pre><code>&lt;bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"&gt;
      &lt;property name="driverClassName" value="${database.driverClassName}" /&gt;
      &lt;property name="url" value="${database.url}" /&gt;
      &lt;property name="username" value="${database.username}" /&gt;
      &lt;property name="password" value="${database.password}" /&gt;
      &lt;property name="testOnBorrow" value="true" /&gt;
      &lt;property name="testOnReturn" value="true" /&gt;
      &lt;property name="testWhileIdle" value="true" /&gt;
      &lt;property name="timeBetweenEvictionRunsMillis" value="1800000" /&gt;
      &lt;property name="numTestsPerEvictionRun" value="3" /&gt;
      &lt;property name="minEvictableIdleTimeMillis" value="1800000" /&gt;
      &lt;property name="validationQuery" value="SELECT 1" /&gt;
      &lt;property name="maxActive" value="1" /&gt;
      &lt;property name="logAbandoned" value="true" /&gt;
      &lt;property name="removeAbandoned" value="true" /&gt;
      &lt;property name="removeAbandonedTimeout" value="10" /&gt;
  &lt;/bean&gt;
  &lt;bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"&gt;
      &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
  &lt;/bean&gt;
  &lt;tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" /&gt;
  &lt;bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"&gt;
      &lt;property name="persistenceUnitName" value="persistenceUnit" /&gt;
      &lt;property name="dataSource" ref="dataSource" /&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p><strong>EDIT 2</strong>:</p>
  
  <p>In MessageServiceImpl:</p>
  
  <pre><code>@Override
      public List&lt;Message&gt; findUnreadMessages(long senderId, long recipientId) {
          System.err.println("thread (service) = " + Thread.currentThread().getName());
          Member sender = memberService.findMember(senderId);
          Member recipient = memberService.findMember(recipientId);
          return messageRepository.findByRecipientAndSenderAndMessageReadFalse(recipient, sender);
      }
  </code></pre>
  
  <p>Relevant aspectJs:</p>
  
  <p>In service aj:</p>
  
  <pre><code>declare @type: MessageServiceImpl: @Transactional;
  </code></pre>
  
  <p>In repository aj:</p>
  
  <pre><code>declare parents: MessageRepository extends JpaRepository&lt;Message, Long&gt;;
  declare parents: MessageRepository extends JpaSpecificationExecutor&lt;Message&gt;;
  declare @type: MessageRepository: @Repository;
  </code></pre>