@Override
  public void setConf(Configuration conf) {
    this.conf = conf;

    if (!initialized) {
      synchronized (TxnHandler.class) {
        if (!initialized) {
          try (DataSourceProvider.DataSourceNameConfigurator configurator =
                   new DataSourceProvider.DataSourceNameConfigurator(conf, POOL_TX)) {
            int maxPoolSize = MetastoreConf.getIntVar(conf, MetastoreConf.ConfVars.CONNECTION_POOLING_MAX_CONNECTIONS);
            if (connPool == null) {
              connPool = setupJdbcConnectionPool(conf, maxPoolSize);
            }
            if (connPoolMutex == null) {
              configurator.resetName(POOL_MUTEX);
              connPoolMutex = setupJdbcConnectionPool(conf, maxPoolSize);
            }
            if (connPoolCompactor == null) {
              configurator.resetName(POOL_COMPACTOR);
              connPoolCompactor = setupJdbcConnectionPool(conf,
                  MetastoreConf.getIntVar(conf, MetastoreConf.ConfVars.HIVE_COMPACTOR_CONNECTION_POOLING_MAX_CONNECTIONS));
            }
          }
          if (dbProduct == null) {
            dbProduct = DatabaseProduct.determineDatabaseProduct(connPool, conf);
            if (dbProduct.isUNDEFINED()) {
              String msg = "Unrecognized database product name <" + dbProduct.getProductName() + ">";
              throw new IllegalStateException(msg);
            }
          }
          if (sqlGenerator == null) {
            sqlGenerator = new SQLGenerator(dbProduct, conf);
          }
          
          initJdbcResource();

          try {
            TxnHandler.ConfVars.init(this::checkIfTableIsUsable, conf);
          } catch (Exception e) {
            String msg = "Error during TxnHandler initialization, " + e.getMessage();
            LOG.error(msg);
            throw e;
          }          
          initialized = true;
        }
      }
    }

    initJdbcResource();

    mutexAPI = new TxnStoreMutex(sqlGenerator, jdbcResource);

    numOpenTxns = Metrics.getOrCreateGauge(MetricsConstants.NUM_OPEN_TXNS);

    timeout = MetastoreConf.getTimeVar(conf, MetastoreConf.ConfVars.TXN_TIMEOUT, TimeUnit.MILLISECONDS);
    replicationTxnTimeout = MetastoreConf.getTimeVar(conf, MetastoreConf.ConfVars.REPL_TXN_TIMEOUT, TimeUnit.MILLISECONDS);
    maxOpenTxns = MetastoreConf.getIntVar(conf, MetastoreConf.ConfVars.MAX_OPEN_TXNS);
    openTxnTimeOutMillis = MetastoreConf.getTimeVar(conf, MetastoreConf.ConfVars.TXN_OPENTXN_TIMEOUT, TimeUnit.MILLISECONDS);

    try {
      transactionalListeners = MetaStoreServerUtils.getMetaStoreListeners(
          TransactionalMetaStoreEventListener.class,
          conf, MetastoreConf.getVar(conf, MetastoreConf.ConfVars.TRANSACTIONAL_EVENT_LISTENERS));
    } catch (MetaException e) {
      String msg = "Unable to get transaction listeners, " + e.getMessage();
      LOG.error(msg);
      throw new RuntimeException(e);
    }

    sqlRetryHandler = new SqlRetryHandler(conf, jdbcResource.getDatabaseProduct());
    txnLockManager = TransactionalRetryProxy.getProxy(sqlRetryHandler, jdbcResource, new DefaultTxnLockManager(jdbcResource));
  }
This is logically part of c'tor and must be called prior to any other method.
Not physically part of c'tor due to use of reflection
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java