BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Java Servlet 3.0がProposed Final Draftに

Java Servlet 3.0がProposed Final Draftに

ブックマーク

原文(投稿日:2009/6/3)へのリンク

Servlet 3.0の主要な目的は、サーブレットとフィルタおよびリスナを開発する際に、アプリケーションのweb.xmlファイルを自分で編集する必要がないようにするというものだ。新しい特性としては以下のものが含まれている。

  • フィルタとサーブレットに対してアノテーションを使用することで、web.xmlに記述する必要なくデプロイできる。
  • webフラグメント("web fragments")がサポートされる。それにより開発者は自分でweb.xmlファイルを編集せずにコンフィグ情報を設定することができる。XMLフラグメントは/META-INF/web-fragment.xmlに配置され、web.xml記述子が使用するものと同じ要素をほぼ全て含むことができる。XMLフラグメントは開発時にはコンテナによって処理されるが、最終的には記述子はまとめられる。
  • ServletContextListenerからフィルタとサーブレットをプログラマティックに設定する。ServletContextListenerはjar中の/META-INF/*.tldファイルから検出される。

Early Draft Review段階においてこれらの特性は議論をひきおこした。エキスパートグループメンバの何人かが懸念したのは、フィルタとサーブレットが意図せずデプロイされてしまう可能性があるということが、それが誤りによるものであれ、考えあぐねた末に起きた混乱によるものであれ、セキュリティ上の重大なリスクであるということだった。きわめて批判的なブログにおいて、エキスパートグループのメンバであるGreg Wilkins氏はこの仕様のことを「貧弱なドキュメントであり、よろしくないプロセスで作業する仲の悪いエキスパートグループが生み出したもの」と称していた。

Proposed Final Draftはこれらの主だった懸念に対して、jarの絶対的な順序を指定できるようにし、同時にそれによって個々のjarファイルを除外できるようにすることで対応した。これは次のように機能する。WEB-INF/libに含まれる各jarは、META-INF/web-fragment.xmlファイル内に<name>要素を記述することで名称を与えられる。その際、webアプリケーションのWEB-INF/web.xmlファイル内の<absolute-ordering>要素において、フラグメントの名称を適用される順に一覧として記述できる。それとあわせて、省略可能な<others/>要素を用いることで、名称をつけられていないjarがインクルードされるのかどうか、また、されるとしたらいつなのかを指定できる。開発者は信頼できるjarだけを選んで一覧に記述できるので、意図しないデプロイを避けることができる。しかもこの順序づけによって、読み込む必要のないjarがweb-fragment.xmlファイルの検出に先立って除外されるので、アプリケーションをデプロイするスピードも上がることになる。

フラグメントとアノテーションの使用をサポートすることに加えてエキスパートグループが自らに課した要件の一つが、webコンテナのトップに構築されるフレームワーク、例えばJAX-WS、JAX-RS、JSFなどの共有コピーをプラグインする機能だった。Public Review Draftの時から追加されているServletContainerInitializerがこのユースケースをあつかう。ServletContainerInitializerはjarサービスAPIによって検出されるものであり、あつかう型の一覧を規定することができる。WEB-INF/libに含まれる全てのjarの中から検出されたクラスで、ここで指定された型のものは全てServletContainerInitializerに渡され、このServletContainerInitializerはServletContextListenerと同じプログラマティックな設定を行うAPIを使用することができる。この機能が追加されたのはよろこばしいことだが、ServletContainerInitializerは新たな争点となっている。Wilkins氏が続くブログ記事で明らかにしているように、ServletContainerInitializerを絶対的な順序指定の機構を用いて除外できるのかどうかが明確でないのだ。氏はこれを明確にするために次のフレーズを追加するよう提案している。

「web.xmlに<absolute-ordering>が記述されていて、そこに<others/>要素が含まれていなかった場合、順序指定で一覧化されたフラグメントを含むjarだけが、アノテーションとプラグインの特性を用いてフィルタ、リスナ、サーブレットをインスタンスかすることができます。特に以下の点が重要です。

  • 除外されたjarのweb-fragment.xmlは処理されない。
  • 除外されたjarの中はアノテーションのついたサーブレット、フィルタ、リスナを検索しない。しかし、除外されたjarに含まれるサーブレット、フィルタ、リスナがweb.xmlもしくは除外されていないweb-fragment.xmlに記述されていれば、metadata-complete属性によって除外されていない限りアノテーションが適用される。
  • 除外されたjarに含まれるTLDファイルからServletContextListenerが検出された場合には、プログラマティックにAPIを使用してフィルタやサーブレットを設定することができない。それが試みられた場合には常にIllegalStateExceptionが発生する。
  • 検出されたServletContainerInitializerが除外されたjarからロードされた場合には無視される。
  • 除外されたjarに対してはServletContainerInitializerがあつかうクラスを見つけるためのスキャンを行わない。」


このような利用を簡単にする特性だけでなく、JSR-315では非同期リクエストが追加され、スレッドがコンテナに結果を返した上で、他のタスクを実行できるようになっている。これもまた論争をひきおこしているのだが、それは既存のRequestDispatcherが非同期の再ディスパッチをあつかえるようにするため、エキスパートグループが骨を折っている時だった。その結果生まれたAPIは仕様にメソッドを20個と新しいインターフェイスを3個付け加えたもので、Public Review段階になって複雑だと方々から批判された。Proposed Final Draftで定義されたのは、特定のディスパッチタイプ、つまりAsyncContext.dispatchであった。これは非同期リクエストに使用されるもので、APIを単純化するのに大いに役立っている。@WebServlet@WebFilterアノテーションはasyncSupported属性を持っている。これはboolean型で、デフォルト値はfalseである。この値がtrueに設定された場合、アプリケーションは別のスレッドにおいて非同期の実行処理を開始することができる。その際にはstartAsyncを呼び、リクエストとレスポンスへ参照を渡し、元のスレッド上のコンテナでの動作を終了する。これはレスポンスが入ってきた時と同じフィルタ(ないしフィルタチェーン)を(逆向きに)たどることを意味している。非同期の実行処理がリクエストに対して開始された場合、もう一方のスレッドないしコールバックは、レスポンスを生成して完了をコールすることもできるし、AsyncContext.dispatchメソッドを使用してリクエストをディスパッチし、コンテナのコンテキスト内で実行されるようすることもできるのだ。

 

この記事に星をつける

おすすめ度
スタイル

BT