接続・切断については以前もブログに書いたように
接続 : /_ah/channel/connected/
切断 : /_ah/channel/disconnected/
にPOSTリクエストが送信されるのでそこにサーブレッドを設置しておけばいい。
ユーザーIDは
ChannelService channelService = ChannelServiceFactory.getChannelService();
ChannelPresence presence = channelService.parsePresence(HttpServletRequest);
String clientId = presence.clientId();
で取得できる。
さて、サーバからクライアントへのメッセージ送信はChannelServiceのsendMessageで行える。
逆にクライアントからサーバへ送信する機能は用意されていないのだろうか。
Google App Engine (Java)のJavadocのChannelServiceを読んでいたところ、ChannelServiceにはparsePresenceメソッド以外にもparseMessageがあることを知った。
接続・切断それぞれに設置されているサーブレッドのリクエストをこのメソッドに入れても、メッセージを作成できずに例外エラーが発生する。
Google App Engine Channel API JavaScript Referenceを読んでも送信に使いそうなメソッドは存在しない。
(function(){
var channel = new goog.appengine.Channel(TOKEN);
window.socket = channel.open();
window.socket.userId = USERID;
})();
このようなスクリプトを使ってSocketオブジェクトをwindow.socketに格納して、Google Chromeの開発者ツールのコンソールからオブジェクトを参照したところ候補にsendメソッドがあった。
そして使ってみると以下のような警告が表示された。
警告: No file found for: /_ah/channel/receive
というわけで/_ah/channel/receiveにサーブレッドを配置したところ、そこでメッセージを受信していることが確認できた。
そしてHttpRequestをparseMessageに渡してChannelMessageを作成することができた。
ChannelService channelService = ChannelServiceFactory.getChannelService();
ChannelMessage channelMessage = channelService.parseMessage(HttpServletRequest);
String fromClientId = channelMessage.clientId();
String message = channelMessage.getMessage();
上記のコードで発信者ユーザIDとメッセージを取得することができた。
しかし、デプロイしたところまだ動作しないようです。
今のところ、代替策はサーバーはクライアント接続時にTokenをキーにIDをキャッシュしておき、クライアントはメッセージ送信の際にTokenを送らせるぐらいでしょうか。
早く正式に提供してほしい機能ですね。
あと、ChannelPresenceとChannelMessageにどのページに作られたChannelなのかを取得するメソッドがほしいですね。