2012年8月9日木曜日

GlassFishで非同期処理(AsyncContext)

J2EE6(Servlet3.0)で、Servletで非同期処理ができるようになりました。
ここでは、GlassFish3.1でServletの非同期処理の設定方法についてご紹介します。
■非同期処理って何?

Servletは通常、ブラウザからリクエストを受け付けたThreadでServletが処理をしてレスポンスをブラウザに返します。
コレが同期処理です。
同期処理で困るのが、Servletでの処理時間が長いと、ブラウザが待たされることです。

コレに対応するのが、非同期処理です。
非同期処理では、ブラウザがらリクエストを受け付けたThreadとは別のThreadで処理をすることができます。

非同期処理は、時間のかかる処理を行うのに使ったり、
Chatなど、レスポンスのタイミングをコントロールしたい時に使用します。

では、非同期処理の実装の仕方。
やることは2つです。
1. HttpServletRequest#startAsync()を使う。
2. web.xmlをServlet3.0対応にし、非同期処理を扱うすべてのルーティーン(FilterとServlet)で非同期処理を有効にする。

では、詳細を。

1. HttpServletRequest#startAsync()を使う。
filterやservletのリクエストを受け取るメソッドの中で、
AsyncContext asyncContext = request.startAsync();
を呼び出します。
それから、
asyncContext.start(Runnable);
で、非同期で処理したい内容を起動します。
例えば、↓みたいな感じです。
final AsyncContext asyncContext = request.startAsync();
asyncContext.start(new Runnable() {
        @Override
        publicvoid run() {
            try {
            //処理時間時間のかかる処理や待ち合わせ処理
            //例えば、チャットの相手の文字入力を待つとか。
            //・・・・
            OutputStream out = asyncContext.getResponse().getOutputStream();
            out.write("complete".getBytes());
            asyncContext.complete();
        } catch (Exception e) {
            log.fatal("exception on wait", e);
        }
    }
 });


2. web.xmlをServlet3.0対応にし、非同期処理を扱うすべてのルーティーン(FilterとServlet)で非同期処理を有効にする。

web.xmlをServlet3.0設定にします。
web.xmlのルートノードを、
<web-appversion="3.0"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
というように設定します。
さらに、filterタグやservletタグの中で、非同期処理をすることを宣言します。

例えば
<servlet>
    <servlet-name>encodingfilter</servlet-name>
    <servlet-class>net.ukiuni.EncodingFilter</servlet-class>
    <async-supported>true</async-supported>
</servlet>
というようにasync-supportedタグを入れます。

この時に重要なのが、リクエストを受け付けるすべての処理(FilterやServlet)でasync-supportedタグを入れる必要がある、ということです。
Servletで処理をする前に、Filterでエンコーディングを設定したり、セキュリティーをかけてることがありますが、そのFilterにもasync-supportedタグを入れる必要があります。

これで、非同期処理ができるようになります。

■追記
あんまりGlassFishっぽくない、汎用的な説明になったので、GlassFishの情報を一つ。
GlassFishには、管理コンソールから「Cometを有効にする」設定ができますが、この設定をOnにしなくても、AsyncContextは使うことができます。

0 件のコメント:

コメントを投稿