2

我尝试按照本教程 - 实现基于 XMPP 的应用服务器 ,使用 Google App Engine 实现 google 的云连接服务器我从http://www.igniterealtime.org/projects/smack/(smack.jar和 smackx.jar)复制了最新的 smack jar ,将它们放在 WEB-INF/lib 中并将它们添加到类路径中(我使用 eclipse)。

在我发布的第一个链接中的代码示例中,XMPPConnection 是在“主”方法中启动的。由于这并不适合 GAE,我创建了一个 ServletContextListener 并将其添加到 web.xml。

public class GCMContextListener implements ServletContextListener {

   private static final String GCM_SENDER_ID = "*GCM_SENDER_ID*";
   private static final String API_KEY = "*API_KEY*";

   private SmackCcsClient ccsClient;

   public GCMContextListener() {
   }

   @Override
   public void contextInitialized(ServletContextEvent arg0) {
       final String userName = GCM_SENDER_ID + "@gcm.googleapis.com";
       final String password = API_KEY;

       ccsClient = new SmackCcsClient();

       try {
           ccsClient.connect(userName, password);
       } catch (XMPPException e) {
           e.printStackTrace();
       }
   }

   @Override
   public void contextDestroyed(ServletContextEvent arg0) {
       try {
           ccsClient.disconnect();
       } catch (XMPPException e) {
        e.printStackTrace();
       }
   }
}

web.xml

<web-app> 
   <listener>
       <listener-class>com.myserver.bootstrap.GCMContextListener</listener-class>
   </listener>
</web-app>

现在,当我启动 GAE 服务器时,出现以下异常:

java.lang.NoClassDefFoundError: javax.naming.directory.InitialDirContext 是一个受限类。有关详细信息,请参阅 Google App Engine 开发人员指南。

我搜索了“Google App Engine 开发人员指南以获取更多详细信息”,但找不到任何相关信息。你能帮我么 ?

4

1 回答 1

2

Google App Engine 限制对某些 JRE 类的访问。事实上,他们发布了一个白名单,向您显示哪些类是可用的。在我看来,Smack 库可能需要一些对目录上下文的引用(也许是为了创建 XMPP 消息?),这就是您的 servlet 导致此异常的原因。javax.naming.directory不在白名单中。

我目前也在设置 GCM 服务器。在我看来,您需要通读该示例并查看该主要方法在做什么。我看到的是与 GCM 服务器的连接:

try {
  ccsClient.connect(userName, password);
} catch (XMPPException e) {
  e.printStackTrace();
}

然后将下游消息发送到设备:

// Send a sample hello downstream message to a device.
String toRegId = "RegistrationIdOfTheTargetDevice";
String messageId = ccsClient.getRandomMessageId();
Map<String, String> payload = new HashMap<String, String>();
payload.put("Hello", "World");
payload.put("CCS", "Dummy Message");
payload.put("EmbeddedMessageId", messageId);
String collapseKey = "sample";
Long timeToLive = 10000L;
Boolean delayWhileIdle = true;
ccsClient.send(createJsonMessage(toRegId, messageId, payload, collapseKey,
    timeToLive, delayWhileIdle));

}

这些操作将在您的应用程序生命周期的某个时间点完成,因此您的 servlet 应该通过提供示例正在实现的方法来支持它们,例如我在此处粘贴的第一段代码中出现的 connect 方法。如果我没记错的话,它的实现在第 235 行的示例中。

正如文档所述,您尝试使用 GAE 实现的第 3 方应用程序服务器应该是:

能够与您的客户沟通。能够向 GCM 服务器发出格式正确的请求。能够使用指数回退处理请求并根据需要重新发送它们。能够存储 API 密钥和客户端注册 ID。API 密钥包含在发送消息的 POST 请求的标头中。能够存储 API 密钥和客户端注册 ID。能够生成消息 ID 以唯一标识它发送的每条消息。

于 2013-09-25T20:44:05.290 回答