FrontPage

ServletAPI 2.5において何が変わったか?

EE5関連のドキュメントをあさっていて見つけました。
面白いので、ぜひ読んでみてください!

以下、私的な解釈とメモです。

J2SE 5.0で行こう!

これまでのServletAPIは概ねJDKとともに歩んできたが、今回のリリースに関しては1.4をすっ飛ばしてJ2SE5.0を取り込んでおり、ServletAPI 2.5のプログラマにJ2SE5.0特有の機能を利用することを保障しているそうです。

  • generics
  • autoboxing
  • foreach
  • enum
  • static importing
  • varargs
  • annotations

これはこれまでの小さな変更とは桁が違うインパクトをもたらします。例えばSE5.0のJavadocを読んでみればわかりますが1.4と比べ言語仕様自体が拡張されています。

アノーテーションでEOD

これはJSR 175として策定されていたメタデータです。
既にC#などではサポートされてるやつでクラスやメソッドに注釈を付加することができ実行時にその注釈を取得できます。
これを利用すると例えば、実行時にフックして依存性を差し込んだりとか、悪名高いSerializableとかClonnableのようなマーカーインタフェースと呼ばれるものを回避することができます。
じゃあ具体的にアノーテーションでは何ができるのかというと、例えばWebService?などではこう書くようです。

import javax.jws.WebService;
import javax.jws.WebMethod;

@WebService
public class HelloWorldService {
  @WebMethod
  public String helloWorld() {
    return "Hello World!";
  }
}

HelloWorldService?クラスをWebService?としてhelloWorldメソッドをWebMethod?とするということです。
説明すら要らないほど直感的です。C#なんかだと[WebMethod?]って書きますね。
これは、EE5.0についてサマリが発表されたときから提唱しているEOD(Ease Of Development)の要となる技術です。もちろんこの機能自体がSE5.0特有の機能に強く依存しています。
またServletAPI2.5でサポートするアノーテーション機能は主に

@Resource、@Resources:

一言で言えばDIと同じでリソースのインジェクションを行い、これを用いることにより手動でのJNDIからのルックアップやweb.xmlへの宣言から開放されるとあります。(ということは、今までのようなサービスロケーターの必要性も薄れるということでしょうか)
そのほかの細かな属性の設定などはアノーテーションの属性で設定することができます

  @Resource javax.sql.DataSource catalog;
  public getData() {
    Connection con = catalog.getConnection();
  }

この場合、caralogがWEBコンテキスト側のJNDIバインド名になります。
そして、このリソースインジェクションについてはサーブレット、サーブレットフィルタ、リスナー、JSPタグ、JSPイベントリスナー、JSFのスコープに属するBean、そのほか少数のサーブレットと関係しないクラスにおいて利用可能だそうです。
@Resourcesはよくわからんのですが、@Resourceの配列ということだそうです。

@PostConstruct?、@PreDestroy?

要するにライフサイクルに関連するもので、あるメソッドに対して付加することによりそのメソッドはライフサイクルメソッドとなります。
@PostConstruct?は、リソースのインジェクションが行われた後に呼び出したいメソッド、@PreDestroy?はインジェクションされたリソースが開放される直前に呼び出したいメソッドに対して付加します。また、そのメソッドはvoid型のインスタンスメソッドでCheckedExeption?をthrowしないものに限られるようです。

@EJB:

@Resourceとほとんど同じでEJBをインジェクションします。
EJB3.0の仕様に関連しています。実際にはEJBというよりEJBのリモートインタフェース型がインジェクションされるということだと思います。

@WebServiceRef?

これも@Resourceとほとんど同じでWebService?をインジェクションします。JAX-WS 2.0の仕様から来ています。

@PersistenceContext?、@PersistenceContexts?、@PersistenceUnit?、@PersistenceUnits?

EJB3.0の改善された永続化機構に由来しています。 「軽快なJava」において

適しているアプリケーションなし
適していないアプリケーションすべてのまともなアプリケーション

と酷評されているEJB2.1までのCMP、BMPに代わる機構です。

@DeclareRoles?、@RunAs?

いわゆるロールベースセキュリティ部分における<security-role><run-as>に代わるもの、JSR250だそうです。

アノーテーション利用時のパフォーマンス

2.5においてコンテナはスタートアップ時にWEB-INF/classesとWEB-INF/libのクラスを嘗め回してアノーテーションを探すらしいです。
もしアノーテーションを利用していないならweb-app要素にfull="true"と加えることでアノーテーションサーチを停められるみたいです。

とりあえず正攻法で拡張

web.xmlでServletとFilterマッピングに関して複数マッピングなどマッピングのパターンが増えたみたいです。
あと、HTTPメソッドが自由に追加できるようになったようです。例えばWebDAVメソッドなどを追加してWebDAVサーブレット(って何?)の開発などに利用できます。
要するに独自のHTTPメソッドが使えるというところでしょうか?
serviceメソッドでrequestからgetMethodして自分でディスパッチすればいいみたいです。

時代は規制緩和

エラーハンドリングに関する制約

これまでは、コンテナがエラーをハンドリングした後、HTTPのステータスコードを変更することはできませんでしたが、正常にハンドリングが行われた時、往々にしてステータスを変更したい場合があります。
その辺の融通が利くようになったということのようです。

Sessionトラッキングに関する制約の緩和

RequestDispatcherにはincludeというメソッドがあり、プログラム的アプローチによりサーバサイドインクルードが可能でした。
しかし、インクルードされたサーブレットのリソースに対して変更を加えることが不可能だったようです。(たぶんセキュリティ上の理由に近かったのかな)
で、この辺が緩和されてResponseが完了していなければ自由にいじれるようです。 ただし、Responseが完了している場合はIllegalStateException?がthrowされるみたいです。
由来はPortletの仕様というのを見て納得しました。Portletって要するにコンポーネントをインクルードしまくるから、その点からこれまでの制約が不自由だったのでしょう。 Velocity(元祖PortletフレームワークのJetSpeed?由来)とかTapestryの活用方法も変化しそうな予感です。

あなた!この際だからハッキリさせましょう。

要するに、あいまいな定義による実装の振る舞いの差異を無くすという、APIのアップデート上順当な部分です。

setContentLength?に関する振る舞いの明確化

厳密に言えば下記のようにContentLength?が0に設定された段階で、それ以降の設定に関しては無視する必要があるが、コンテナ実装によっては可能になっているので、Content-Lengthが0より大きいときのみ可能と定義したみたいです。

response.setHeader("Host", "localhost");
response.setHeader("Pragma", "no-cache");
response.setHeader("Content-Length", "0");
response.setHeader("Location", "http://www.apache.org");

request.setCharacterEncoding?()の振る舞い

いやいや、これは悪名が高いですねw
まずはここを読んでみてください。

この要求の本体で使用される文字エンコーディングの名前を
オーバーライドします。このメソッドは、要求パラメータの
読み取り、または getReader() を使用した入力の読み取りに
先立って呼び出す必要があります。

そうなんです。じゃあsetCharacterEncoding?しなおせば別なエンコーディングでReaderを取得できるのか?ということについては言及がないんです。
これに関して、Readerを呼び出した後は何も起きないと明確に定義されました。 EE5のAPIドキュメントにも下記の一文が盛り込まれています。

Otherwise, it has no effect.

かくいう私も、過去にこれではまりまして、Tomcat4のソースコードをあさった経験があります。
結局そのときは、Tomcat4では一度Readerを呼び出した後は設定しても無駄という実装だったので、それに従いました。orz

クロスコンテキストセッション

きたーーー!まさに禁断の領域です。w
リクエストがアプリケーションコンテキストを渡り歩きます。
現状でもServletContextからgetContext(java.lang.String uripath)すれば別なコンテキストを取得できますが、その際のセッションに関する規定が存在しませんでした。
やったことないけど、現状では多分セッション自体は共有されない実装だと思います。
しかし、2.5ではクロスコンテキストなセッション利用が可能になります。これもPortletで重要な機能だからうんぬんと書いてあります。

こんなのもあったはず

今のところ、以下に関しては次回のレビュー(筆者のかな?仕様策定に関してかな?)にまわすとあります。

NIOのChannel利用による高効率な処理

そのまんまです。詳しくはIBMのdeveloperWorksの記事を読んでください。

FilterにおけるwrapされたRequest,Responseに対する立場

FilterにおいてRequestやResponseをラップすることがよくありますが、コンテナはラップされたものを呼ぶのかオリジナルを呼ぶのかをハッキリさせようぜということっぽいです・・・。

ServletをWelcome fileに指定できるの?

明確な規定がないようです。 でも、まあ、現状ではTomcatでもできてます。っていうか知らずにやってましたorz

Welcome fileのディスパッチルールってどうなってんの?

現状では厳密に定義されていないから、互換性に問題があるようです。

ログイン後のデフォルトページってどうやって選ばれてるの?

はい、これ、ついこの前はまりました。現状では明確な指定はできません。 ちなみにTomcat5.5では認証が必要なリソースを開いた時、最初にアクセスしている保護されたコンテンツに飛ばされます。 例えばヘッダ領域でCSSとかJSとか指定してるとログイン後になぜかそこに飛ばされちゃうということです。w

プログラマティックなログインを行った場合にServletはセキュリティ情報を取れないよね?

これは多分ServletAPIの提供している認証方法ではなく、よく行われる独自の認証を行ったときのことについての話です。現状では独自の方法で認証を行った場合は、すべてを独自で作る必要があり非常に面倒です。

最後に

長くなりましたが、ServletAPI 2.5はなかなか良い感じの仕上がりのようです。 登場が待ち遠しいですね。 ちなみに、現在ServletAPI 2.5をサポートしているコンテナは下記2つだけだそうです。

  • Jetty6
  • SunのGlassFish?

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: 2010-03-14 (日) 07:00:40 (2718d)