public void testLoggingAutoActivate() throws Throwable {
    assertFalse(
        "Auto-logging of misuse of the wrapper should be off",
        BorrowedConnectionProxy.isCallStackTraced());

    UserTransaction txn = transactionService.getUserTransaction();
    Connection connection;
    try {
      txn.begin();
      // Dig the proxy out of ... somewhere
      ConnectionHolder conHolder =
          (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
      connection = conHolder.getConnection();
      txn.commit();
    } catch (Throwable e) {
      try {
        txn.rollback();
      } catch (Throwable ee) {
      }
      throw e;
    }
    // Now mess with the connection, which is protected by the Hibernate wrapper
    try {
      connection.commit();
      fail("Use case should have generated a HibernateException");
    } catch (HibernateException e) {
      // Expected
    }
    assertTrue(
        "Auto-logging of misuse of the wrapper should now be on",
        BorrowedConnectionProxy.isCallStackTraced());

    // Now start a new transaction and we should see logging
    txn = transactionService.getUserTransaction();
    try {
      txn.begin();
      // Dig the proxy out of ... somewhere
      ConnectionHolder conHolder =
          (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
      connection = conHolder.getConnection();
      txn.commit();
    } catch (Throwable e) {
      try {
        txn.rollback();
      } catch (Throwable ee) {
      }
      throw e;
    }
    // Now mess with the connection, which is protected by the Hibernate wrapper
    try {
      connection.commit();
      fail("Use case should have generated a HibernateException");
    } catch (HibernateException e) {
      // Expected
    }
    // Check for error logs
  }
  public Connection getConnection(DataSource dataSource) {
    ConnectionHolder connectionHolder =
        (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

    if (connectionHolder == null) {
      return null;
    } else {
      return connectionHolder.getConnection();
    }
  }
  @Override
  protected void doBegin(Object transaction, TransactionDefinition definition) {
    JpaTransactionObject txObject = (JpaTransactionObject) transaction;

    if (txObject.hasConnectionHolder()
        && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
      throw new IllegalTransactionStateException(
          "Pre-bound JDBC Connection found! JpaTransactionManager does not support "
              + "running within DataSourceTransactionManager if told to manage the DataSource itself. "
              + "It is recommended to use a single JpaTransactionManager for all transactions "
              + "on a single DataSource, no matter whether JPA or JDBC access.");
    }

    try {
      if (txObject.getEntityManagerHolder() == null
          || txObject.getEntityManagerHolder().isSynchronizedWithTransaction()) {
        EntityManager newEm = createEntityManagerForTransaction();
        if (logger.isDebugEnabled()) {
          logger.debug("Opened new EntityManager [" + newEm + "] for JPA transaction");
        }
        txObject.setEntityManagerHolder(new EntityManagerHolder(newEm), true);
      }

      EntityManager em = txObject.getEntityManagerHolder().getEntityManager();

      // Delegate to JpaDialect for actual transaction begin.
      final int timeoutToUse = determineTimeout(definition);
      Object transactionData =
          getJpaDialect()
              .beginTransaction(
                  em,
                  new DelegatingTransactionDefinition(definition) {
                    @Override
                    public int getTimeout() {
                      return timeoutToUse;
                    }
                  });
      txObject.setTransactionData(transactionData);

      // Register transaction timeout.
      if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
        txObject.getEntityManagerHolder().setTimeoutInSeconds(timeoutToUse);
      }

      // Register the JPA EntityManager's JDBC Connection for the DataSource, if set.
      if (getDataSource() != null) {
        ConnectionHandle conHandle = getJpaDialect().getJdbcConnection(em, definition.isReadOnly());
        if (conHandle != null) {
          ConnectionHolder conHolder = new ConnectionHolder(conHandle);
          if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) {
            conHolder.setTimeoutInSeconds(timeoutToUse);
          }
          if (logger.isDebugEnabled()) {
            logger.debug(
                "Exposing JPA transaction as JDBC transaction ["
                    + conHolder.getConnectionHandle()
                    + "]");
          }
          TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
          txObject.setConnectionHolder(conHolder);
        } else {
          if (logger.isDebugEnabled()) {
            logger.debug(
                "Not exposing JPA transaction ["
                    + em
                    + "] as JDBC transaction because JpaDialect ["
                    + getJpaDialect()
                    + "] does not support JDBC Connection retrieval");
          }
        }
      }

      // Bind the entity manager holder to the thread.
      if (txObject.isNewEntityManagerHolder()) {
        TransactionSynchronizationManager.bindResource(
            getEntityManagerFactory(), txObject.getEntityManagerHolder());
      }
      txObject.getEntityManagerHolder().setSynchronizedWithTransaction(true);
    } catch (TransactionException ex) {
      closeEntityManagerAfterFailedBegin(txObject);
      throw ex;
    } catch (Exception ex) {
      closeEntityManagerAfterFailedBegin(txObject);
      throw new CannotCreateTransactionException(
          "Could not open JPA EntityManager for transaction", ex);
    }
  }