【问题标题】:NullPointerException when making XMPP connection through Smack 4.2.0通过 Smack 4.2.0 建立 XMPP 连接时出现 NullPointerException
【发布时间】:2017-09-20 03:10:23
【问题描述】:

我打算使用 Smack 通过 Firebase CCS 发送消息。我为我的 Web 应用程序修改了一个简单的 CCS 客户端,但是当我尝试建立连接时,它会导致异常。 我正在使用 Smack 4.2.0

这是连接的过程。

1) 我的客户端的连接方式:

public void connect() throws XMPPException{
        try{
            config = XMPPTCPConnectionConfiguration.builder()
                    .setPort(Config.FCM_PORT)
                    .setHost("fcm-xmpp.googleapis.com")
                    .setXmppDomain("googleapis.com")
                    .setSecurityMode(/*Default; Explicit setting for emphasis*/SecurityMode.ifpossible)
                    .setSendPresence(true)
                    .setUsernameAndPassword(fcmServerUsername, mApiKey)
                    .setSocketFactory(SSLSocketFactory.getDefault())
                    .setDebuggerEnabled(mDebuggable)/* Launch a window with info about packets sent and received */
                    .build();
        }
        catch(XmppStringprepException e){
            e.printStackTrace();
        }

        connection = new XMPPTCPConnection(config);


        // Configuring Automatic reconnection
        ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
        manager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
        manager.enableAutomaticReconnection();

        // Connect now then login
        try{
            connection.connect();
            connection.login();
        }
        // TODO: Handle the exceptions if possible appropriately
        catch(SmackException sme){
            logger.severe(sme.getMessage());
            sme.printStackTrace();
        }
        catch(IOException ioe){
            logger.severe(ioe.getMessage());
            ioe.printStackTrace();
        }
        catch(InterruptedException ie){
            logger.severe("Connection got interrupted!!");
            ie.printStackTrace();
        }
    }

2)我跟踪了异常,并在这里找到了它:(Smack 的来源)

在线 - HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());

// AbstractXMPPConnection.java
protected List<HostAddress> populateHostAddresses() {
        List<HostAddress> failedAddresses = new LinkedList<>();
        if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }
        // Either the populated host addresses are not empty *or* there must be at least one failed address.
        assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
        return failedAddresses;
    }

异常是NullPointerException,我发现getDNSResolver()返回null。在我引用的所有来源中,没有任何与 DNS 解析器相关的内容,因为它应该由 Smack 内部处理。所以我的问题是,我是否错过了一些关键的配置或建立连接的步骤?

编辑:我在这里问是因为 Smack 是一个庞大的库,并且可能有人知道我可能错过了一些配置。我无法直接设置 DNSResolver

【问题讨论】:

  • @MartinW :我在这里问是因为 Smack 是一个庞大的库,并且可能有人知道我可能错过了一些配置。我无法直接设置 DNSResolver。
  • 所以真正的问题不是 NPE,而是您需要帮助正确配置库。试着询问一下。

标签: java smack


【解决方案1】:

不确定在 4.2.0 但在 4.2.2(和更高版本)中,您需要 smack-resolver-dnsjava-4.2.2.jar 在您的类路径中,smack 调用包中包含的 DNSUtil,如果该类不存在它返回 NullPointerException。

希望对您有所帮助! 大卫

【讨论】:

  • 很长一段时间我都期待找到这个错误。感谢实施 'org.igniterealtime.smack:smack-resolver-dnsjava:4.2.3'
【解决方案2】:

编辑:答案更新

这不是 Smack 源代码中的错误,因为他们的 4.2.0 升级指南明确提到:

**

API 更改

**

警告:此列表可能不完整

介绍ConnectionConfiguration.setHostAddress(InetAddress)

在以前版本的 Smack 中, ConnectionConfiguration.setHost(String) 可用于设置 XMPP 服务的主机 IP 地址。这不再可能,因为 添加了 DNSSEC 支持。您必须使用新的连接配置 ConnectionConfiguration.setHostAddress(InetAddress) 代替。


这似乎是一个错误,因为我通过提供主机地址(应该从 {Host, Domain} 推断出)解决了它。那么,我怎么知道要提供主机地址呢?

诀窍就在这里:(Smack 来源)

// AbstractXMPPConnection.java

if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }

您可以在此处查看 if、else-if 块,并且由于 else if (config.host != null) 块中出现异常,我提供了 hostAddress 以便它永远不会进入该块并且它起作用了。

我知道这是对实际问题的一种破解,但这似乎是 Smack 4.2.0 中的一个错误,除非有人反驳我。

奖励信息:如果在纠正此问题后,您在登录时遇到 Base 64 编码的另一个异常,请参阅此 - XMPP client using Smack 4.1 giving NullPointerException during login

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多