MessageSenderスレッドは全てのHttpResponseに対して5秒毎に時刻を送信するので、中身はリスト25のようになる。

リスト25 CometSampleServlet.javaのMessageSenderクラス

public class MessageSender implements Runnable {
    protected boolean running = true;
  
    public void stop() {
        running = false;
    }
 
    public void run() {
        while (running) {
            Date date = new Date();
            // 全てのクライアントにデータを送信
            for (int i = 0; i < connections.size(); i++) {
                try {
                    PrintWriter writer = connections.get(i).getWriter();
                    writer.println(date + "<br>");
                    writer.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                // 5秒休む
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

web.xmlにはリスト26のように、このサーブレットを有効にするための設定を追加する。

リスト26 WEB-INF/web.xmlに設定を追加

<servlet>
    <servlet-name>CometSampleServlet</servlet-name>
    <servlet-class>sample.CometSampleServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>CometSampleServlet</servlet-name>
    <url-pattern>/CometSampleServlet</url-pattern>
</servlet-mapping>

そして、TomcatがNew I/Oを利用するように、$CATALINA_HOME/conf/server.xmlにおける該当するポート(この場合は8080番)のConnectorの設定をリスト27のように修正する。protocol属性に「org.apache.coyote.http11.Http11NioProtocol」を指定することで、New I/Oによる非ブロックの通信を行えるようになる。

リスト27 $CATALINA_HOME/conf/server.xmlを修正

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" connectionTimeout="20000"
redirectPort="8443" />

Tomcatを再起動してアプリケーションをデプロイし、ブラウザから「http://localhost:8080/Tomcat6Comet/CometServletSample」(アプリケーション名を"Tomcat6Comet"とした場合)にアクセスすると、図29のように5秒毎に時刻が表示される。

図29 5秒毎に時刻が表示される

なお、このサンプルはリアルタイムにデータを表示させるためにコネクションを張ったままデータを送り続けるという、いささか強引なプログラムになっているため、ブラウザの処理方法によっては正常に表示されない。スレッドの処理も簡略化してあるため、負荷が大きいので注意が必要だ。

本当の意味でリアルタイムのデータ表示を実現するならば、クライアント側でAjaxなどを利用して非同期な通信を行うのがいいだろう。そうすればサーバがレスポンスを返すまで待つ必要がなく、Cometの真価を十分に発揮できるようになる。

まとめ

Apache Tomcatの最初のバージョンがリリースされたのは(当時はまだApacheのトップレベルプロジェクトではなかったが)1999年のことであり、オープンソースのサーブレットコンテナとしては最古参の存在と言える。現在では無償で利用できるサーブレットコンテナが他にも多数あるが、未だにTomcatの人気は根強く、JBossのようにアプリケーション・サーバ内にバンドルしている製品も多い。

そのTomcatがJava EE 5の主要機能であるServlet 2.5/JSP 2.1に対応するのを、多くの開発者が待ち望んでいた。本稿ではTomcat 6.0.10で追加された機能を利用したいくつかのプログラム例を紹介したが、それ以外にもメモリ使用効率の改善や実装のリファクタリングなど、目立たない部分でも多くの改良が加えられている。ただし、本文でも書いたようにJ2SE 5.0以降のJavaが必須になっている点は要注意だ。

6系は長い間alphaリリース扱いだったが、ようやく安定版である6.0.10がリリースされた。TomcatベースのツールやTomcatをバンドルした製品、開発環境なども6系への対応を進められている。現段階では、EclipseやNeBeansといった主要プロダクトのサポートが不十分だが、それら整った暁には、移行を前向きに検討すべきだろう。Tomcatを使用している/使用する予定のあるユーザは、今後の動向に注目しておく必要があるだろう。