NoClassDefFoundError:javax.naming.directory.InitialDirContext是受限制的类。在Google App Engine中使用CCS(GCM)

时间:2013-08-13 15:29:30

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

我试图按照本教程使用Google App Engine实施谷歌的云连接服务器 - Implementing an XMPP-based App Server。我从http://www.igniterealtime.org/projects/smack/(smack.jar和smackx.jar)复制了最新的smack罐子,将它们放在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开发人员指南以获取更多详细信息”,但无法找到任何相关信息。你能帮帮我吗?

1 个答案:

答案 0 :(得分:2)

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实现的,应该是:

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