查找 InitialContext.lookup 检索到的数据源的定义位置?

Find Where Data Source retrieved by InitialContext.lookup is defined?

我正在调试的 JBoss 服务器上 运行 有一些其他人编写的 Java 代码(早已消失,无法联系他们)运行。这行代码得到了 javax.sql.DataSource

DataSource ds = new InitialContext().lookup("java:/jdbc/WPDS");

但是,当他们在下一行使用 ds.getConnection() 时,日志中会显示:

...

javax.resource.ResourceException: Unable to get managed connection for jdbc/WPDS

...

Caused by: org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (java.sql.SQLException: ORA-01017: invalid username/password; logon denied)

我环顾四周,发现了一个名为 oracle-xa-ds.xml 的文件。它包含以下内容:

<datasources>
  <xa-datasource>
    <jndi-name>jdbc/WPDS</jndi-name>
    <!-- uncomment to enable interleaving <interleaving/> -->
    <isSameRM-override-value>false</isSameRM-override-value>
    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
    <xa-datasource-property name="URL">jdbc:oracle:thin:@hostname.hidden.com:1621:HIDE</xa-datasource-property>
    <xa-datasource-property name="User">hidden</xa-datasource-property>
    <xa-datasource-property name="Password">hidden</xa-datasource-property>
    <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
    <!-- Checks the Oracle error codes and messages for fatal errors -->
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
    <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
    <no-tx-separate-pools/>

    <max-pool-size>50</max-pool-size>

      <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
      <metadata>
         <type-mapping>Oracle9i</type-mapping>
      </metadata>
  </xa-datasource>

  <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
         name="jboss.jca:service=OracleXAExceptionFormatter">
    <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
  </mbean>

</datasources>

我已经确认所有这些设置都是正确的。我可以使用此文件中提供的主机名、端口、SID、用户名和密码连接到数据库。

我怀疑它可能从其他地方加载了 DataSource,但我不知道如何验证该理论(如果它是真的,我将如何找出它实际从哪里获取它?)是否有某种我可以启用的 JNDI 日志记录,或者我可以通过某种方式让它告诉我它正在尝试使用什么username/password(这样我就可以看到它是否正在使用文件中的内容?)

您可以尝试像这样获取信息,但不是密码。

  if (dataSource instanceof  oracle.jdbc.xa.client.OracleXADataSource) {
      oracle.jdbc.xa.client.OracleXADataSource oracleXADataSource = (oracle.jdbc.xa.client.OracleXADataSource)dataSource;
      logger.info(oracleXADataSource.getUrl());
      logger.info(oracleXADataSource.getUsername());
  }

ORA-01017:无效username/password;登录被拒绝

原因:

  • 尝试登录 Oracle 时输入了无效的用户名或密码。用户名和密码必须与 GRANT CONNECT 语句中指定的相同。如果用户名和密码一起输入,则格式为:username/password。

  • ORA-01017 错误的核心问题是用户 ID 和密码组合无效,但除了密码不正确,还有用户 ID 问题

  • 可能是目标系统的用户 ID 无效 - 该用户 ID 作为用户名列存在于 dba_users 视图中。

  • 检查您的 $ORACLE_SID 环境参数。如果您的 $ORACLE_SID 设置为错误的系统 ID,那么您可能会收到 ORA-01017 错误,因为您连接到错误的数据库。

  • 检查您的 tnsnames.ora 以确保 TNS 服务名称指向正确的服务器和实例名称。如果指定的 tnsnames.ora 服务名称不正确,则该数据库中可能不存在用户 ID 和密码。

操作:

  • 以正确的格式输入有效的用户名和密码组合。

  • 用户名和密码绝对不正确。

  • 试试 ALTER SYSTEM SET SEC_CASE_SENSITIVE_LOGON = FALSE;并更改密码。

http://oracle-base.com/articles/11g/case-sensitive-passwords-11gr1.php

我最终写了一个方法,它递归地反映一个对象并打印很多关于它的信息。

我最终发现它使用的是 oracle-xa-ds.xml 中的完全相同的密码 - 问题是该文件中的密码不正确。所以我整整两天都在输入错误的密码上浪费了时间。

希望这段代码能帮助其他人快速结束他们的徒劳追逐,让他们回到正确的方向:

public static final void logFields(Object o, String prefix, int depth) {
    if (depth <= 0) {
        logger.debug(prefix + "No deeper because max depth reached.");
        return;
    }

    if (o == null) {
        return;
    }

    Class  c         = o.getClass();
    String className = c.getName();
    if (className.startsWith("java.lang")) {
        logger.debug(prefix + "No deeper because class is " + className);
        return;
    }

    logger.debug(prefix + "Class Name: " + className);
    for (Field f : c.getDeclaredFields()) {
        logger.debug(prefix + "Field Name: " + f.getName());
        logger.debug(prefix + "Field Type: " + f.getType());
        try {
            if (!f.isAccessible()) {
                logger.debug(prefix + "  Not accessible - fixing that.");
                f.setAccessible(true);
                logger.debug(prefix + "  Should now be accessible.");
            }
            Object o2 = f.get(o);
            logger.debug(prefix + "Field Value: " + o2);
            logFields(o2, prefix + "    ", depth - 1);
        } catch (Throwable t) {
            logger.debug(prefix + "Caught Throwable trying to get Field Value: " + t);
            logger.error(t, t);
        }
    }
}

要使用它,只需执行以下操作:

logFields(ds, "", 7);