GCM サービスは初めてです。サンプル コードは、基本的に、appspot.com でホストされているサーバー アプリにコピーしました。null 引数のメッセージを送信しようとするとエラーが発生しますが、どれがどれかわかりません。appspot.com のログは次のとおりです。
2012-07-20 14:57:11.042 /sendMessage 500 8ms 0kb AppEngine-Google; (+http://code.google.com/appengine)
0.1.0.2 - - [20/Jul/2012:14:57:11 -0700] "POST /sendMessage HTTP/1.1" 500 0 "http://mouseworldgcm.appspot.com/sendAll" "AppEngine-Google; (+http://code.google.com/appengine)" "mouseworldgcm.appspot.com" ms=9 cpu_ms=23 api_cpu_ms=0 cpm_usd=0.000708 queue_name=gcm task_name=3983469213642671348 instance=00c61b117c1533caf348700f9435ffa04e7119
C 2012-07-20 14:57:11.040
Uncaught exception from servlet
javax.servlet.UnavailableException: java.lang.IllegalArgumentException: argument cannot be null
at org.mortbay.jetty.servlet.ServletHolder.makeUnavailable(ServletHolder.java:415)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:458)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:263)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:202)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:171)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:123)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:477)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:449)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:455)
at com.google.tracing.TraceContext.runInContext(TraceContext.java:695)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:333)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:325)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:453)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
at java.lang.Thread.run(Thread.java:679
/sendAll サーブレットは次のとおりです。
package com.joebutt.mouseworldgcm;
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import java.io.IOException;
import java.util.List;
//import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet that adds a new message to all registered devices.
* <p>
* This servlet is used just by the browser (i.e., not device).
*/
@SuppressWarnings("serial")
public class SendAllMessagesServlet extends BaseServlet {
/**
* Processes the request to add a new message.
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
List<String> devices = Datastore.getDevices();
String status;
if (devices.isEmpty())
{
status = "Message ignored as there is no device registered!";
}
else
{
Queue queue = QueueFactory.getQueue("gcm");
// NOTE: check below is for demonstration purposes; a real application
// could always send a multicast, even for just one recipient
if (devices.size() == 1) {
// send a single message using plain post
String device = devices.get(0);
queue.add(withUrl("/sendMessage").param(SendMessageServlet.PARAMETER_DEVICE, device));
status = "Single message queued for registration id " + device;
} else {
// send a multicast message using JSON
String key = Datastore.createMulticast(devices);
queue.add(withUrl("/sendMessage").param(SendMessageServlet.PARAMETER_MULTICAST, key));
status = "Multicast message queued for " + devices.size() + " devices";
}
req.setAttribute(HomeServlet.ATTRIBUTE_STATUS, status.toString());
getServletContext().getRequestDispatcher("/home").forward(req, resp);
}
}
}
そのため、週末中ずっと働いた後、ヌルエラーは送信者が原因であると判断しました。そこで、他のドキュメントのように標準タイプに変更しました。問題は、401 エラー コードが表示されることです。APIキーをリセットし、ブラウザアプリとサーバーAPIキーの両方を試しましたが、どちらもまだ401エラーをスローしています。
Sender の作成方法に関する提案はありますか????
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
//sender = newSender(config); //this is the line I changed
sender = new Sender(ApiKeyInitializer.ATTRIBUTE_ACCESS_KEY);
}
/**
* Creates the {@link Sender} based on the servlet settings.
*/
protected Sender newSender(ServletConfig config) {
String key = (String) config.getServletContext()
.getAttribute(ApiKeyInitializer.ATTRIBUTE_ACCESS_KEY);
return new Sender(key);
}