java - 通过 Smack 4.2.0 进行 XMPP 连接时出现 NullPointerException

标签 java smack

我打算使用 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;
    }

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

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

最佳答案

编辑:答案更新

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

**

API Changes

**

Warning: This list may not be complete

Introduced ConnectionConfiguration.setHostAddress(InetAddress)

In previous versions of Smack, ConnectionConfiguration.setHost(String) could be used to set the XMPP service's host IP address. This is no longer possible due to the added DNSSEC support. You have to use the new connection configuration ConnectionConfiguration.setHostAddress(InetAddress) instead.

<小时/>

这似乎是一个错误,因为我通过提供主机地址(应该从 {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 block ,并且由于 else if (config.host != null) block 中出现异常,因此我提供了 hostAddress,以便它永远不会进入该 block 它起作用了。

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

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

关于java - 通过 Smack 4.2.0 进行 XMPP 连接时出现 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43571101/

相关文章:

java - 在没有本地 persistence.xml 的情况下使用 JPA @StaticMetamodel 类? (远程 EJB)

Java - 如何在 if 语句中添加 rgb 值?

android - XMPP注销(Smack API)而不断开与服务器的连接

android - 如何解决 客户端未连接或不再连接。你在login()之前调用了connect()吗?

xmpp - Openfire 是否支持通过 Http-Bind 的 TLS?如果不是,还有什么选择

xmpp - 无法使用Smack更改我的用户的状态

java - 列表中的映射 - 如何使用 Stream 进行迭代

Java SubnetUtils 抛出 java.lang.IllegalArgumentException

java - TCP 连接 - 服务器仅在关闭套接字后发送消息

android - 为什么即使 session 中不存在 SESSION,openfire 的用户仍保持在线状态