連載
» 2010年06月14日 00時00分 公開

現場にキく、Webシステムの問題解決ノウハウ(7):サーブレットやJSPの“バージョン”意識してますか?

本連載は、日立製作所が提供するアプリケーションサーバ「Cosminexus」の開発担当者へのインタビューを通じて、Webシステムにおける、さまざまな問題/トラブルの解決に効くノウハウや注意点を紹介していく。現在起きている問題の解決や、今後の開発のご参考に(編集部)

[@IT編集部,@IT]

10年で「J2EE 1.2」から「Java EE 6」へ

 1999年にJ2EE 1.2がリリースされてから10年以上経過し、2009年12月には4回目のバージョンアップ版であるJava EE 6がリリースされた(参考:米Sun、軽量、モジュラー化を進めた「Java EE 6」を公開)。

 この間、多くの技術が実装され、またエンハンスされてきたが、エンハンスに伴って以前のバージョンと振る舞いが変わってしまったケースが少なからず存在する。

 サーブレット/JSPは、J2EE 1.2リリース当初から存在する歴史と実績のある技術だ。Java EEを適用するほとんどのシステムで利用されている。歴史がある分、多数の機能追加が行われてきたのと同時に、若干だが仕様の変更も行われている。さらに、あいまいだった仕様が明確にされたがために、アプリケーションサーバによっては、振る舞いが変わってしまったものもある。

 今回は、振る舞いの変更に起因するトラブル事例と、その回避策を紹介しよう。

【事例1】サーブレットリスナの振る舞い

 サーブレットリスナを使うと、サーブレットの開始や終了、セッションの作成や破棄などのイベントに応じて処理できる。

 Servlet 2.4では、リスナの延長で実行されているコードで例外が発生した場合の仕様が明確にされた。リスナの延長で実行されているコードで例外が発生すると、エラーページに遷移するか、エラーページが定義されていなければ、クライアントにステータス「500」を返し、かつそのイベントに応じたリスナが複数あったとしても、リスナの呼び出しは打ち切られることが明記された。

 一方、Servlet 2.3では、リスナの延長で例外が発生したときの仕様は未定義であり、実装依存だった。

 よって、1つのイベントに対して複数のリスナが定義されていると、バージョンによっては動きに差異が生じる可能性がある。つまり、Servlet 2.3に準じて実装されているコンテナは、リスナで例外が発生しても、エラーページに遷移せず、かつ複数のリスナをすべて実行するかもしれないのだ。

図1 Servlet 2.3実装依存の挙動 図1 Servlet 2.3実装依存の挙動

 複数リスナをすべて実行することを前提としてアプリケーションを実装していると、Servlet 2.4仕様のコンテナ上では期待通りの動作をしなくなってしまう。

図2 Servlet 2.4の仕様に明記された挙動 図2 Servlet 2.4の仕様に明記された挙動

【事例2】JSPのpageEncoding属性による文字化け

 JSP 2.0の仕様では国際化が強く意識され、JSP 1.2における国際化のあいまいな仕様が明確にされた。その1つにpageディレクティブpageEncoding属性の有効範囲がある。JSP 2.0の仕様では、pageEncoding属性の適用範囲は、その属性が記述されたファイルだけであること、includeディレクティブでincludeするファイルには適用されないことが明記された。

 よって、JSP 2.0に準じたコンテナを使った場合、includeするファイルにpageEncoding属性の指定がなく、かつ日本語を使った場合(に限らないが、ISO-8859-1で表現できない文字が含まれている場合)には、文字化けが発生する。

 JSP 1.2では、includeするファイルのpageEncodingについての規定がないため、コンテナによっては、include元のファイルのpageEncodingを引き継ぎ、文字化けが発生しない。

図3 JSP 1.2ではpageEncoding適用範囲は実装依存だった 図3 JSP 1.2ではpageEncoding適用範囲は実装依存だった

 この動きに依存したJSPアプリケーションは、JSP 2.0の仕様のコンテナにアップグレードした途端に文字化けに悩むことになるだろう。

図4 JSP 2.0で明確になったpageEncoding適用範囲 図4 JSP 2.0で明確になったpageEncoding適用範囲

 JSP/サーブレットの文字化けに関する対策については、下記記事を参考にしてほしい。

Javaの文字化け対策FAQ
JSP/サーブレット・プログラミングで誰もが一度は遭遇するトラブルが文字化けだ。4回の連載で文字化け解消のポイントを解説する

Java TIPS
Javaプログラミングに役立つテクニックとノウハウ集
サーブレット2.3における文字エンコーディングの指定
サーブレット2.2における文字エンコーディングの指定
文字コード宣言をフィルタで共有化する
リソースファイルの内容が文字化けする場合には
リソースファイルで他国語対応サイトを構築する

最新仕様のコンテナにアップグレードするには

 最新仕様のコンテナにアップグレードしたいが、「実績あるアプリケーションを変更したくない」「アプリケーションが大きすぎで、アップグレードに伴う検証をする時間がない」という場合も多いことだろう。

 例えばCosminexusのアプリケーションサーバでは、web.xmlスキーマ定義によって、「どのバージョンの挙動をするか」決定しているため、最新仕様のコンテナにアップグレードするときでも、旧バージョンで実績のあるアプリケーションは一切、直す必要がないという。

DTD/XMLスキーマ バージョン
http://java.sun.com/j2ee/dtds/web-app_2_2.dtd 2.2
http://java.sun.com/dtd/web-app_2_3.dtd 2.3
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd 2.4
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd 2.5
表 DTD/XMLスキーマとWebアプリケーションバージョンの対応

 どのスキーマを指定しても最新仕様の動きになるアプリケーションサーバも存在する一方、Cosminexusは旧バージョンからの移行性を重視しているようだ。

スキーマ定義と期待するバージョンが一致しない場合

 スキーマ定義によらず、最新仕様の動きになるアプリケーションサーバ上でアプリ開発すると、スキーマ定義のバージョンと、アプリケーションが期待するバージョンが一致していない場合がある。例えば、スキーマでは2.3を指定しているにもかかわらず、2.4から採用されたJSP属性を利用している場合などがある。

 このようなアプリケーションに対応するためには、「アプリケーションサーバの機能に頼る」のも、1つの手段だ。

 例えばCosminexusの場合は、web.xml以外の手段でアプリケーションのバージョンを指定できるという。webserver.application.lower_versionプロパティをユーザープロパティファイルに指定すると、web.xmlに指定されたバージョンを無視し、指定したバージョンの挙動になるそうだ。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。