Java EE 7では,HTML5を使用するWeb開発者のニーズに応えて,多数の新API の導入や既存APIの変更が行われている。関係する領域は3つある – JSON操作のための新API,新たな属性に対応した JSFの大幅な更新,そしてもうひとつが,HTML5を形成する数多くのテクノロジのひとつであるWebSocketプロトコルを扱う新APIだ。
WebSocketプロトコルは,Webサーバがクライアントの要求に対応する方法を変える – コネクションをクローズする代わりに101ステータスを送信して,コネクションはオープンしたままにするのだ。これによって,ストリーム上に存在するメッセージの受信と,ストリーム上へのメッセージの送信が可能になると期待される。HTTPとは違って全2重通信をサポートしているため,クライアント – 通常はブラウザ – とサーバは,同じタイミングでメッセージを相互に送信することができるからだ。
このプロトコルはIETF RFC6455によって定義されている。
WebSocketでコネクションを確立するには,クライアントがWebSocketハンドシェイク要求を送信し,サーバが応答を返信する。以下にその例を示す。
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
Server response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
一旦ハンドシェイクが実行されれば,クライアントとサーバは接続されて通信ピア(peer)となり,メッセージの送受信が可能になる。そして最後にコネクションを切断する。
クライアント側はW3Cが定義したAPIを使って,JavaScriptで処理を記述する。
JavaのWebSocketアプリケーションはWebSocketエンドポイントで構成される。WebSocketエンドポイントとは,2つのピア間のWebSocketコネクションの片端を表現したJavaオブジェクトである。
Java WebSocket APIは,RemoteEndpointインターフェースのインスタンスをエンドポイントとして,セッションの各ピアをモデル化する。このインターフェースと2つのサブタイプ(RemoteEndpoint.WholeとRemoteEndpoint.Partial)には,エンドポイントからピアにWebSocketメッセージを送信するためのさまざまなメソッドが含まれている。
エンドポイントの生成には,おもに2つの方法がある。ひとつは,エンドポイントのライフサイクル操作,メッセージの受送信,サービスの公開,あるいはピアへの接続といった,所定の処理を行うJava WebSocket APIの特定のクラスを実装することだ。
session.addMessageHandler(new MessageHandler.Whole<String>() {
public void onMessage(String text) {
try {
remote.sendText("Got your message (" + text + "). Thanks !");
} catch (IOException ioe) {
ioe.printStackTrace();
} }
もうひとつは,Java WebSocket APIのアノテーションを使用して,POJO (Plain Old Java Object) をデコレートする方法だ。アプリケーション側の実装では,これらアノテートされたPOJOクラスを使って,実行時に必要なオブジェクトを生成し,それをWebSocketエンドポイントとしてデプロイすればよい。
@ServerEndpoint("/hello")
public class MyHelloServer {
@OnMessage
public String handleMessage(String message) {
return "Got your message (" + message + "). Thanks !"; } }
MessageHandlersへの登録には,ひとつのSessionに対して,ネイティブなWebSocketメッセージタイプ (テキスト,バイナリ,pong) 毎にひとつのMessageHandler,という制限がAPIによって課されている。ただし将来的には変更されるかも知れない。
エンドポイントは,WebSocketコネクションを確立するための,接続開始時のハンドシェイクに関与する。その後はエンドポイントを通じて,さまざまなメッセージの送受信が行われる。そしてWebSocketのコネクションが閉じられると,エンドポイントのライフサイクルも終了する。
ピアからのWebSocketクローズイベントを受信した結果として,あるいは下位実装においてコネクションをクローズする理由があったために,WebSocketエンドポイントに対してオープンしているコネクションをクローズする場合には,WebSocket実装はWebSocketエンドポイントのonClose()メソッドをコールしなければならない。
Java EE 7に導入される以前も,WebSocketアプリケーションをJavaで実装することは,もちろん可能だった。しかしそのために使用可能な多数のAPIの仕様がそれぞれ微妙に違っているため,例えばApache Tomcat 7用に記述したWebSocketアプリケーションは,JettyやJBoss,Resin用に修正しなければならなかった。これを行うための標準化されたメソッドがJava EEで用意されることは,歓迎を持って迎えられるものだ。