title: Pre-bound JDBC Connection found with multi-war ear
body: <p>We are getting the error </p>
  
  <blockquote>
    <p>org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.</p>
  </blockquote>
  
  <p>The place where it happens is where we override the transaction manager, so that we can react to the doBegin, commit and rollback methods.  However, the error occurs in the doBegin where we call the super.doBegin() and before any of our code has actually run.  The error is also highly intermittent and uncooperative in terms of happening when we want it to.</p>
  
  <p>I see online many people suggesting that this usually means you have TWO transaction managers defined.  I initially rejected this as applying to us because we don't.  I double checked.  But, not so fast, maybe I do.  While our wars only have one tx manager, the app where this is happening...the ONLY app where this is happening...is two wars in the same EAR.  Each has it's own spring context defined and it's own txManager.  Could they be conflicting?  Might this be the source of our troubles?</p>
  
  <p>update - </p>
  
  <p>app-config.xml (at least the parts that might be relevant...I left alot of mundane bean definitions out)</p>
  
  <pre><code>    &lt;bean id="dataSource" name="enoteDataSource dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
              &lt;property name="resourceRef"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt; 
              &lt;property name="jndiName"&gt;
                  &lt;value&gt;${ds.jndi}&lt;/value&gt;
              &lt;/property&gt;
          &lt;/bean&gt;
      &lt;bean id="sessionFactory" name="sessionFactory enoteSessionFactory" class = "org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt;
          &lt;property name="dataSource"&gt;&lt;ref local="dataSource" /&gt;&lt;/property&gt;
          &lt;property name="packagesToScan"&gt;
              &lt;list&gt;
                  &lt;value&gt;gov.usdoj.afms.enote.model.*&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;
      &lt;bean id="txManager" name="txManager transactionManager" class="gov.usdoj.afms.umc.utils.hibernate.AfmsHibernateTransactionManager"&gt;
          &lt;property name="sessionFactory" ref="enoteSessionFactory" /&gt;
      &lt;/bean&gt; 
      &lt;!--  some of the transaction are controlled in code through annotation --&gt;
      &lt;tx:annotation-driven transaction-manager="txManager"/&gt;
      &lt;!-- the transactional advice (what 'happens'; see the &lt;aop:advisor/&gt; bean below) --&gt;
      &lt;tx:advice id="txActionAdvice" transaction-manager="txManager"&gt;
          &lt;!-- the transactional semantics... --&gt;
          &lt;tx:attributes&gt;
              &lt;tx:method name="deleteUser"  propagation="REQUIRES_NEW" rollback-for="BOException" /&gt;
              &lt;tx:method name="*"  propagation="REQUIRES_NEW" /&gt;
          &lt;/tx:attributes&gt;
      &lt;/tx:advice&gt;
      &lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt;
       &lt;!-- the transactional semantics... --&gt;
      &lt;tx:attributes&gt;
          &lt;!-- all methods starting with 'fetch' are read-only --&gt;
          &lt;tx:method name="fetch*" isolation="READ_UNCOMMITTED"/&gt;
          &lt;!-- other methods use the default transaction settings (see below) --&gt;
          &lt;tx:method name="*" rollback-for="Throwable" /&gt;
      &lt;/tx:attributes&gt;
      &lt;/tx:advice&gt;
    &lt;aop:config&gt;
     &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.ActionPanelService.*(..))"
        advice-ref="txActionAdvice"/&gt;      
  
      &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.AccountInfoService.*(..))"
        advice-ref="txAdvice"/&gt;
  
     &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.PersonalInfoService.*(..))"
        advice-ref="txAdvice"/&gt;
  
     &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.CreateUserService.*(..))"
        advice-ref="txAdvice"/&gt;
  
     &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.UM04Service.*(..))"
        advice-ref="txAdvice"/&gt;      
  
      &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.LookupService.removeUsrOrgLvlAsgnT(..))"
        advice-ref="txAdvice"/&gt;
  
      &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.LookupService.addOrUpdateUsrOrgLvlAsgnT(..))"
        advice-ref="txAdvice"/&gt;
  
      &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.LookupService.removeAndAddUsrOrgLvlAsgnT(..))"
        advice-ref="txAdvice"/&gt;
  
     &lt;aop:advisor 
        pointcut="execution(* gov.usdoj.afms.umc.services.St60Service.*(..))"
        advice-ref="txAdvice"/&gt;      
  
    &lt;/aop:config&gt;
  
      &lt;bean id="serviceTarge" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
        &lt;property name="transactionManager" ref="txManager" /&gt;
        &lt;property name="target" ref="createUserService" /&gt;
        &lt;property name="transactionAttributes"&gt;
          &lt;props&gt;
              &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
              &lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
              &lt;prop key="*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
          &lt;/props&gt;
        &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="UM04ServiceTarget" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
        &lt;property name="transactionManager" ref="txManager" /&gt;
        &lt;property name="target" ref="UM04Service" /&gt;
        &lt;property name="transactionAttributes"&gt;
          &lt;props&gt;
              &lt;prop key="*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
          &lt;/props&gt;
        &lt;/property&gt;
      &lt;/bean&gt; 
  
      &lt;bean id="umcLookups" class="gov.usdoj.afms.umc.application.lookups.UMCLookups" init-method="init" scope="singleton"&gt;
          &lt;property name="lookupDao" ref="LookupDao"/&gt;
      &lt;/bean&gt;
  
      &lt;bean id="userSearchServiceBean" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
        &lt;property name="proxyInterfaces"&gt;
        &lt;value&gt;gov.usdoj.afms.umc.services.UserSearchService&lt;/value&gt;
      &lt;/property&gt;
          &lt;property name="target"&gt;
              &lt;ref bean="userSearchServiceImpl"/&gt;
          &lt;/property&gt;
          &lt;property name="interceptorNames"&gt;
              &lt;list&gt;              
                  &lt;value&gt;theLogger&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;     
      &lt;/bean&gt;
  </code></pre>
  
  <p>The txManager override is there so we can set some values to the CLIENT_INFO which allows us to identify a user and module with the transaction so our audit triggers record the info.</p>
  
  <pre><code>@Override
  protected void doBegin(Object arg0, TransactionDefinition arg1)
  {
      super.doBegin(arg0, arg1);
      if (!Db2ClientInfo.exists()) {
          clearDBProperty();
      } else {
          setDBProperty(Db2ClientInfo.getClientUserId(), Db2ClientInfo.getClientApplicationId());
      }
  }
  
  @Override
  protected void doCommit(DefaultTransactionStatus status) {
      super.doCommit(status);
      clearDBProperty();
  }
  
  
  @Override
  protected void doRollback(DefaultTransactionStatus status) {
      super.doRollback(status);
      clearDBProperty();
  }
  
  @SuppressWarnings("deprecation")
  private void setDBProperty(String uId, String appName) {
      Session session = getSessionFactory().getCurrentSession();
  
      Properties props = new Properties();
      props.setProperty(WSConnection.CLIENT_ID, uId);
      props.setProperty(WSConnection.CLIENT_APPLICATION_NAME, appName);
      try {
          Connection nativeConn = new SimpleNativeJdbcExtractor().getNativeConnection(session.connection());
          if (nativeConn instanceof WSConnection) {
              WSConnection wconn = (WSConnection) nativeConn;
              wconn.setClientInformation(props);
          } else {
              logger.error("Connection was NOT an instance of WSConnection so client ID and app could not be set");
          }
      } catch (Exception e) {
          throw new RuntimeException("Cannot set DB parameters!", e);
      }
  }
  
  /**
   * Why clear this?  Because we use a connection POOLER and we'd like to clear this info when it is checked into the pool.
   */
  private void clearDBProperty() {
      setDBProperty("", "");
  }
  </code></pre>