【问题标题】:NoClassDefFoundError: javax.naming.directory.InitialDirContext is a restricted class. Using CCS (GCM) in Google App EngineNoClassDefFoundError: javax.naming.directory.InitialDirContext 是一个受限类。在 Google App Engine 中使用 CCS (GCM)
【发布时间】:2013-08-13 15:29:30
【问题描述】:

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

在我发布的第一个链接中的代码示例中,XMPPConnection 是在“main”方法中启动的。由于这并不适合 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 开发人员指南以获取更多详细信息”,但找不到任何相关信息。你能帮帮我吗?

【问题讨论】:

    标签: google-app-engine google-cloud-messaging


    【解决方案1】:

    Google App Engine 限制对某些 JRE 类的访问。事实上,他们发布了whitelist,向您展示了哪些类是可用的。在我看来,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 以唯一标识它发送的每条消息。

    【讨论】:

    • 我能够使用“旧”http 协议实现 gcm。我只是假设,如果谷歌发布了一些新的做事方式,它将得到他们现有基础设施的支持。他们的云应用服务器应该支持 Google Cloud Messaging 我错了吗?显然我是。
    • 他们文档中的广告库 (Smack) 由于其白名单而无法在 GAE 基础架构上运行,这似乎很奇怪。即使他们声明第三方服务器的实现取决于开发人员,在这种情况下似乎 GAE 的 PaaS 方法也缺乏。为了使用新的 GCM 实现,我不得不将我的服务器部署在不同的提供商中。另一种方法是使用另一个库而不是 Smack,它不需要 JNI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    相关资源
    最近更新 更多