我试图按照本教程使用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开发人员指南以获取更多详细信息”,但无法找到任何相关信息。你能帮帮我吗?
答案 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以唯一标识它发送的每条消息。