8.2.4 Servlet 3.0/3.1仕様で追加,変更された仕様についての注意事項
Servlet 3.0/3.1仕様で追加,変更された仕様を,アプリケーションサーバ上で使用するときの注意事項を示します。Servlet 3.1仕様,Servlet 3.0仕様およびServlet 2.5仕様については,それぞれの仕様書(Servlet 3.1仕様書,Servlet 3.0仕様書,Servlet 2.5仕様書)を参照してください。
(1) Servlet 3.0とアプリケーションサーバの機能を組み合わせた場合の仕様
Servlet 3.0で追加された機能と,アプリケーションサーバの機能を組み合わせた場合の仕様について説明します。
(a) Webプリケーションのバージョン設定機能
Webアプリケーションのバージョン設定機能で,バージョンとして3.0以降は設定できません。
(b) META-INF/resources以下のJSP事前コンパイル
Servlet 3.0仕様では,JSPファイルをJARファイルの中のMETA-INF/resourcesの階層に含めることができるようになりましたが,META-INF/resources内にJSPを含むWebアプリケーションの場合,JSPの事前コンパイルは実行できません。JSP事前コンパイルを実行した場合,META-INF/resources内のJSPは事前コンパイルされないで,リクエスト実行時にエラーとなります。
(c) アプリケーションのリロード
Servlet 3.0/3.1仕様の機能を使用したアプリケーションをリロードする場合,次の制約があります。
META-INF/resourcesに静的コンテンツ(JSPも含む)を持つJARファイルを含むアプリケーションの場合,JARファイルを更新してリロードしても,JARファイルのMETA-INF/resources内の静的コンテンツは更新前のものにしかアクセスできません。META-INF/resourcesに静的コンテンツを持つJARファイルを含むアプリケーションをリロードした場合,KDJE39556-Wが出力されます。
- 注意事項
-
09-00-02より前のバージョンの場合,次のアプリケーションをリロードしたときの動作は保証されません。
-
ServletContainerInitializerインタフェースの実装クラスを含むアプリケーションの場合。
リロードした場合,KDJE39557-Wが出力されます。
-
動的サーブレット定義で追加したサーブレット,フィルタまたはリスナを含むアプリケーションの場合。
リロードした場合,KDJE39558-Wが出力されます。
-
(d) APIで定義したサーブレットでのrun-as機能
APIで定義したサーブレットでrun-as機能を使用できません。次の設定をした場合,無視されます。
-
サーブレットのクラスで@RunAsアノテーションを使用する。
-
ServletRegistration.DynamicインタフェースのsetRunAsRoleメソッドを呼び出す。
(e) APIで定義したサーブレットまたはフィルタの実行時間の監視
APIで定義したサーブレットまたはフィルタでは,J2EEアプリケーションの実行時間の監視機能を使用できません。cosminexus.xmlに<method-observation-timeout>タグが設定されていても無視されます。
(f) Webアプリケーションの呼び出し時のHTTPセッションの継続
Webアプリケーションの呼び出し時のHTTPセッションの継続については,Servlet 2.5仕様の場合と同じ動作となります。詳細は,「8.2.5(6) Webアプリケーションの呼び出し時のHTTPセッションの継続について」を参照してください。
(g) アノテーション参照抑止機能
Servlet3.0で追加されたアノテーションのうち,@HandlesTypesアノテーションはアノテーション参照抑止機能の対象になりません。アノテーション参照抑止機能が有効な場合でも処理されます。
(2) Servlet 3.0以降とCDIを組み合わせた場合について
Servlet 3.0以降とCDIを組み合わせて使用する場合,Servlet 3.0以降に対応したweb.xmlを使用してください。これ以外のバージョンのweb.xmlとCDIを組み合わせて使用できません。
(3) APIで定義したフィルタまたはリスナと,@PostConstructアノテーションまたは@PreDestroyアノテーションを組み合わせた場合について
APIで定義したフィルタまたはリスナでは,@PostConstructアノテーションまたは@PreDestroyアノテーションを使用できません。これらのアノテーションを使用した場合,無視されます。
(4) インクルード時に対象のコンテンツがない場合について
Servlet 3.0仕様では,インクルードの対象がデフォルトサーブレット(静的コンテンツを提供するためにコンテナが用意しているサーブレット)で,対象のコンテンツがない場合,FileNotFoundException例外をスローすることになっています。また,その例外がユーザプログラムで処理されなかった場合,レスポンスはコミットされないで,ステータスコード500を返すことなっています。
アプリケーションサーバでは,この仕様はサポートされません。08-70以前のバージョンと同様にステータスコード404が返されます。
(5) エスケープシーケンスの使用について
Servlet 3.0以降で新規に追加されたAPIやプロパティの入力文字に,エスケープシーケンス(\b,\t,,\n,\f,\r,\",\',\\)を使用しないでください。使用した場合,ログが途中で改行されるなど,表示が不正になることがあります。
(6) 動的サーブレット定義について
動的サーブレット定義について,アプリケーションサーバで使用した場合にServlet 3.0/3.1仕様と異なる点について説明します。
(a) サーブレット,フィルタ,またはリスナの定義
-
APIおよびweb.xmlの両方でフィルタを追加した場合に,APIで定義されたほかのフィルタマッピングのisMatchAfterメソッドがfalseに設定されているときは,リクエスト処理の中でAPIの定義が先に呼ばれます。
-
APIおよびweb.xmlの両方でリスナを定義した場合,リスナの生成のときはアプリケーションの開始時にweb.xmlで定義されたリスナが先に読み込まれます。リスナを削除するときは,APIの定義が先に読み込まれます。
-
URLパターンに空文字("")を指定してjavax.servlet.ServletRegistrationインタフェースのaddMapping(String... urlPatterns)メソッドを呼び出した場合,サーブレットはコンテキスト名だけでアクセスされます。コンテキスト名も空文字("")の場合は,サーブレットにアクセスできません。
-
すでにweb.xmlで定義された名称,または@WebServletアノテーションでサーブレットクラスが生成された名称と同じサーブレット名を指定して,addServlet()メソッドを呼び出さないでください。
-
ユーザアプリケーションの中で,同じサーブレットに対してsetMultipartConfig()メソッドを呼び出し,@MultipartConfigアノテーションを指定した場合,setMultipartConfig()メソッドで指定した値が使用されます。
同様に,ユーザアプリケーションの中で,同じサーブレットに対してsetServletSecurity()メソッドを呼び出し,@ServletSecurityアノテーションを指定した場合,setServletSecurity()メソッドで指定した値が使用されます。
-
getRunAsRole()メソッドおよびsetRunAsRole(String roleName)メソッドを使用して,ロールの取得および設定はできません。また,ワーニングメッセージまたはエラーメッセージも出力されません。
-
すでに登録されている名称でサーブレットまたはフィルタを登録した場合,アプリケーションの開始時にKDJE39552-Wが出力され,処理は続行されます。
-
URLパターンに改行コードが含まれていた場合,アプリケーションの開始時にKDJE39555-Wが出力され,処理は続行されます。
(b) ServletContainerInitializerインタフェースを使用した定義
アプリケーションサーバでのServletContainerInitializerインタフェースを使用した定義について,Servlet 3.0仕様と次の点が異なります。
-
ServletContainerInitializerインタフェースを実装したクラスを含むJARファイルは次の場所に配置できます。
-
アプリケーションに含まれるWARファイル内のWEB-INF/libディレクトリ
-
WEB-INF/libディレクトリ以外の場所
WEB-INF/libディレクトリ以外の場所に,ServletContainerInitializerインタフェースを実装したクラスを含むJARファイルを配置する場合,JARファイルの絶対パスをusrconf.propertiesの次のプロパティに指定します。WEB-INF/libディレクトリにあるJARファイルを指定した場合の動作は保証しません。
webserver.ServletContainerInitializer_jar.include.path
- 設定例
-
webserver.ServletContainerInitializer_jar.include.path=C:/Program Files/xxx/foo/lib/bar.jar
-
-
@HandlesTypesアノテーションのクラスの検索範囲は,ServletContainerInitializerインタフェースの実装クラスを含むWARの中です。WARのWEB-INF/classesディレクトリにあるクラス,およびWEB-INF/libディレクトリにあるJARファイルが対象となります。
-
ServletContainerInitializerインタフェースを実装したクラスを含むJARファイルが読み込めないか処理できない場合,アプリケーションの開始時にKDJE39548-Eが出力され,アプリケーションの開始に失敗します。
-
@HandlesTypesアノテーションで指定したクラスを継承(extends)や実装(implements)したクラス,または@HandlesTypesアノテーションで指定したクラスのアノテーションを付けているクラスを検索する際に,クラスのロードに失敗した場合,KDJE39549-Wが出力され,アプリケーションの開始処理は続行されます。
-
webserver.ServletContainerInitializer_jar.include.pathに指定した,ServletContainerInitializerインタフェースを実装したクラスを含むJARファイルが見つからない場合,またはJARファイルもしくはファイルが読み込めない場合,アプリケーションの開始時にKDJE39553-Wが出力され,処理は続行されます。このメッセージはwebserver.ServletContainerInitializer_jar.include.pathに指定されたJARファイルごとに出力されます。
-
webserver.ServletContainerInitializer_jar.include.pathに指定した,ServletContainerInitializerインタフェースを実装したクラスを含むJARファイルがクラスパスの中に見つからない場合,アプリケーションの開始時にKDJE39554-Wが出力され,処理は続行されます。このメッセージはwebserver.ServletContainerInitializer_jar.include.pathに指定されたJARファイルごとに出力されます。
(7) ファイルアップロードについて
ファイルアップロードについて,アプリケーションサーバで使用した場合にServlet 3.0/3.1仕様と異なる点について説明します。
-
web.xmlおよび@MultipartConfigアノテーションの両方でmultipart config要素を設定した場合,web.xmlの定義が優先されます。
-
リクエストタイプがmultipart/form-data以外のリクエストでファイルアップロードを実施した場合,javax.servlet.ServletException例外がスローされます。ファイルアップロードを実施するリクエストのタイプと実行結果を次の表に示します。
表8‒13 ファイルアップロードを実施するリクエストのタイプと実行結果 web.xmlまたは@MultipartConfigアノテーションを指定したリクエストのタイプ
実行結果
mime-multipart以外
javax.servlet.ServletException例外がスローされます。
multipart/form-data以外のmime-multipart
javax.servlet.ServletException例外がスローされます。
multipart/form-data
ファイルアップロードが実行されます。例外は発生しません。
-
MultipartConfigElementがプログラムで定義された場合,web.xmlで定義された場合と同じ動作になります。ただし,空文字("")がlocationに指定された場合,ファイルがWebアプリケーションの作業ディレクトリに格納されます。
-
アップロードされたファイルが,web.xmlの<file-size-threshold>タグまたは@MultipartConfigアノテーションのfileSizeThreshold属性で指定した値よりも大きいサイズの場合,リクエスト内のオブジェクトの一部分に対応する一時ファイルが生成されます。一時ファイルの名称は,「upload」から始まる,一意に識別される名称で,拡張子は「.tmp」です。
例:upload__5f8d5c62_1316c5ef08b__8000_00000012.tmp
一時ファイルはリクエストの処理の最後に削除されます。ただし,一時ファイルが開かれたままの場合,J2EEサーバが正常に停止されなかった場合,システムダウンした場合など,一時ファイルが削除されないケースがあります。このような場合は,locationで指定した場所から一時ファイルを手動で削除する必要があります。
ユーザが手動で作成したファイルと同じ名称の一時ファイルが生成された場合は,ユーザが作成したファイルが上書きされます。
-
Partオブジェクトはリクエスト内で利用できます。Partオブジェクトはリクエストが完了した時点で削除されます。あとで利用するためにセッションの中でPartオブジェクトを保持しても,動作は保証されません。
(8) 静的リソースの配置について
静的リソースの配置について,アプリケーションサーバで使用した場合にServlet 3.0/3.1仕様と異なる点について説明します。
-
静的リソースが含まれるJARファイルが読み込めないか処理できない場合,アプリケーションの開始時にKDJE39548-Eが出力され,アプリケーションの開始に失敗します。
-
指定したJARファイルに形式不正があった場合,アプリケーションの開始時にKDJE39550-Eが出力され,処理は続行されます。
-
WEB-INF/libに不正なJARファイル,または読み込めないファイルが含まれていた場合,アプリケーションの開始時にKDJE39551-Wが出力され,そのJARファイルを無視して処理が続行されます。
(9) APIについて
APIについて,アプリケーションサーバで使用した場合にServlet 3.0/3.1仕様と異なる点について説明します。
-
アプリケーションサーバでは,Servlet 3.0/3.1仕様で追加されたAPIのうち,次の表に記載されていないAPIを使用できます。APIの詳細については,Servlet 3.1の仕様書を参照してください。
次の表に記載された非サポートのAPIを使用した場合の挙動は,表下の注釈を参照してください。
表8‒14 非サポートのAPI(Servlet 3.0/3.1) 項番
パッケージ
クラス
インタフェース/クラス
メソッド
機能
1
javax.servlet
ServletContext
インタフェース
getJspConfigDescriptor※1
JSP
2
getVirtualServerName※2
Servlet
3
javax.servlet.descriptor
JspConfigDescriptor
インタフェース
すべてのメソッド※3
JSP
4
JspPropertyGroupDescriptor
インタフェース
すべてのメソッド※3
JSP
5
TaglibDescriptor
インタフェース
すべてのメソッド※3
JSP
6
javax.servlet.http
HttpSessionIdListener
インタフェース
すべてのメソッド※4
Servlet
7
HttpServletRequest
インタフェース
changeSessionId※5
Servlet
8
HttpServletRequestWrapper
インタフェース
changeSessionId※5
Servlet
-
Servlet 2.5仕様に対応するWebアプリケーションで,Servlet 3.0以降で追加されたAPIは使用できません。使用した場合,チェックされないため動作は保証されません。
-
SessionTrackingModeでは,SSLは使用できません。アプリケーションサーバではCOOKIEとURLだけ使用できます。
(10) web.xmlの省略について
Servlet 3.0/3.1仕様では,次のアプリケーションの場合,web.xmlを省略できます。
-
静的コンテンツおよびJSPだけを含むWebアプリケーション(サーブレット,フィルタ,およびリスナを含まない)
-
サーブレット,フィルタ,リスナをアノテーションで定義したWebアプリケーション
(11) セッションIDを示すHTTP Cookie名の変更について
セッションIDを示すHTTP Cookie名を変更する場合,Cookie名に「csfcfc」を指定できません。
また,使用できる文字に次の条件があります。条件に違反した場合,KDJE39559-Wが出力されます。セッションの不正な動作の原因になることがあるため,条件に合った文字を使用してください。
-
ASCII文字を使用してください。ただし,次の文字は使用できません。
「#」,「(」,「)」,「<」,「>」,「@」,「,」,「;」,「:」,「\」,「/」,「"」,「[」,「]」,「?」,「=」,「{」,「}」
-
空白,および制御文字は使用できません。
-
文字列の先頭に「$」は使用できません。
(12) Webアプリケーションで使用できるHTTP Cookie名
WebアプリケーションでHTTP Cookieを使用する場合,次の名称を指定できません。なお,大文字と小文字は区別されません。
-
HTTPセッションのセッションIDで使用するHTTP Cookieの名称。デフォルトは「JSESSIONID」。
-
グローバルセッションを表すHTTP Cookieの名称。デフォルトは「GSESSIONID」。
-
J2EEサーバのサーバID付加機能によってサーバIDを付加したHTTP Cookieの名称と同じ名称。
-
J2EEサーバ内部で使用するHTTP Cookieの名称「csfcfc」。
(13) <servlet-class>要素に指定するクラスについて
web.xmlの<servlet-class>要素を省略する場合,@WebServletアノテーションを指定したjavax.servlet.http.HttpServletのサブクラスをWebアプリケーションに含め,name属性に<servlet-class>要素を省略したサーブレットのサーブレット名を設定する必要があります。該当するHttpServletクラスがない場合は,KDJE39339-Eが出力され,サーブレットクラスのロードに失敗します。
(14) <filter-class>要素に指定するクラスについて
web.xmlの<filter-class>要素を省略する場合,@WebFilterアノテーションを指定したjavax.servlet.Filterの実装クラスをWebアプリケーションに含め,filterName属性に<filter-class>要素を省略したフィルタのフィルタ名を設定する必要があります。該当するFilterクラスがない場合は,KDJE39340-Eが出力され,アプリケーションの開始に失敗します。
(15) セッションIDを示すHTTP CookieのPath属性の変更について
セッションIDを示すHTTP CookieのPath属性を変更する場合,別のWebアプリケーションとセッションIDを示すHTTP Cookie名やPath属性が重複すると,HTTP CookieのセッションIDを示す値が上書きまたは削除されるなどの理由で,HTTPセッションが正しく引き継がれなくなることがあります。
(16) セッションIDを示すHTTP CookieのPath属性とDomain属性に使用できる文字について
セッションIDを示すHTTP CookieのPath属性とDomain属性に使用できる文字には次の条件があります。条件に違反した場合,KDJE39559-Wが出力されます。セッションの不正な動作の原因になることがあるため,条件に合った文字を使用してください。
-
Path属性には,ASCII文字だけが使用できます。ただし,制御文字およびセミコロン(;)は使用できません。
-
Domain属性には,英数字,ハイフン(-)およびピリオド(.)だけが使用できます。
(17) 非同期サーブレットの場合の注意事項
ここでは,Servlet仕様に明記されていない挙動やServlet仕様と異なる挙動について説明します。
-
アプリケーションサーバではCDIが有効なアプリケーションで非同期サーブレットを実行できません。実行した場合,WELD-000335,WELD-000714,WELD-000715またはWELD-000717のメッセージが出力されることがあります。デフォルトではCDIが有効になります。非同期サーブレットを利用するには,ejbserver.javaee.cdi.beansXmlRequiredにtrueを指定して,アーカイブにbeans.xmlを含めないで,CDIを無効にしてください。CDIの無効化については,マニュアル「アプリケーションサーバ 機能解説 基本・開発編(コンテナ共通機能)」の「9.3.1 CDIの対象となるアプリケーション」を参照してください。
-
Servlet仕様では,AsyncContext.complete()メソッドの呼び出しによってレスポンスをコミットすることが記載されていますが,そのタイミングについては明記されていません。アプリケーションサーバでは,別スレッドでAsyncListener.onComplete()を呼び出したあとにレスポンスをコミットします。このため,タイミングによってはAsyncContext.complete()を呼び出したあとに,レスポンスへの書き込みができる場合があります。AsyncContext.complete()を呼び出したあとに書き込んだ内容が,レスポンスに出力されるか,レスポンスバッファに残って意図しない出力をするかは,実行するタイミングに依存するため,AsyncContext.complete()を呼び出したあとのレスポンスへの書き込みは実装しないでください。
なお,startAsyncメソッドを呼び出したサーブレットのserviceメソッドが終了するまでは,complete()を呼び出したあとのレスポンスコミットとonCompleteメソッド呼び出しは実行されず,ServletRequest.isAsyncStarted()メソッドがtrueを返すことは,Servlet仕様に明記された仕様です。
-
Servlet仕様では,AsyncContext.start(Runnable)でコンテナ管理のスレッドに委譲した非同期処理で例外が発生した場合に,コンテナがAsyncListgener.onError(AsyncEvent)を呼ぶかどうかは明記されていません。アプリケーションサーバでは,AsyncContext.start(Runnable)を呼び出したサーブレットのserviceメソッドが終了したあとに例外が発生した場合は,AsyncListgener.onError(AsyncEvent)を呼び出しません。
-
Servlet仕様では,AsyncContextのdispatchメソッド実行中に例外が発生した場合のコンテナのふるまいについて,次の記述があります。
-
コンテナがAsyncListgener.onError(AsyncEvent)を呼び出す。
-
リスナーがcompleteメソッドもdispatchメソッドも呼ばない場合は,ステータスコード500でエラー遷移する。
-
対応するエラーページが見つからないか,エラーページでcompleteメソッドもdispatchメソッドも呼ばない場合は,コンテナがAsyncContext.complete()を呼び出す。
アプリケーションサーバでは,コンテナがonErrorメソッドを呼び出したあとに,web.xmlのerror-page要素に指定されたエラーページに遷移しません。dispatch先で発生した例外がerror-page要素のexception-typeの指定にマッチする場合は,onErrorメソッドを呼び出す前に指定されたエラーページに遷移します。また,例外が発生した場合には,error-page要素のerror-codeで指定したエラーページには遷移しません。
-
-
javax.servlet.AsyncContext.addListener(AsyncListener)実行後にjavax.servlet.AsyncEvent.getSuppliedRequest()またはgetSuppliedResponse()メソッドを実行すると,Servlet API仕様に記載の期待値と異なった値が返されます。
- <期待値>
-
null
- <実際の値>
-
javax.servlet.ServletRequestのstartAsyncメソッド実行時に使用されているjavax.servlet.ServletRequestまたはServletResponse実装クラスのインスタンス
-
次のメソッドについて,Servlet API仕様に記載されているjava.lang.IllegalStateExceptionが発生しない場合があります。
-
javax.servlet.AsyncContext.addListener(AsyncListener)
-
javax.servlet.AsyncContext.addListener(AsyncListener, ServletRequest, ServletResponse)
-
javax.servlet.AsyncContext.setTimeout(long)
-
javax.servlet.AsyncContext.getRequest()
-
javax.servlet.AsyncContext.getResponse()
-
-
javax.servlet.http.WebConnection.getInputStream()またはgetOutputStream()メソッドについて,Servlet API仕様に記載されているjava.io.IOExceptionが発生しない場合があります。
-
javax.servlet.AsyncContext.setTimeout(long)の引数に0以下の値(タイムアウトなし)を設定していて,アプリケーション停止時に,webserver.context.stop_asyncwait_timeoutに設定した待ち時間を経過しても非同期処理が完了していない場合,コンテナが非同期タイムアウトを試み,AsyncListenerが存在する場合はonTimeoutメソッドを呼び出します。
-
サーバ停止時に非同期処理が完了していない場合は,webserver.context.stop_asyncwait_timeoutやjavax.servlet.AsyncContext.setTimeout(long)の設定値に関わらず,コンテナが非同期タイムアウトを試み,AsyncListenerが存在する場合はonTimeoutメソッドを呼び出します。
-
次の条件をすべて満たす場合に,javax.servlet.ServletRequest.isAsyncStarted()メソッドはServlet API仕様に記載の期待値とは異なった値を返します。
-
非同期サイクルにリスナを登録する
-
javax.servlet.ServletRequestのstartAsyncメソッドを呼び出したのと同じjavax.servlet.Servlet.serviceメソッド内でjavax.servlet.AsyncContext.complete()メソッドを呼び出す
-
登録したリスナのonComplete()メソッドjavax.servlet.ServletRequest.isAsyncStarted()メソッドを呼び出す
- <期待値>
-
false
- <実際の値>
-
true
-
-
非同期サーブレットでは,次に示すメソッドの第二引数としてjavax.servlet.http.HttpServletResponseのインスタンスが渡されます。
- HttpServletResponseが引数として渡される非同期サーブレットのメソッド
-
・doDelete(HttpServletRequest, HttpServletResponse)
・doGet(HttpServletRequest, HttpServletResponse)
・doHead(HttpServletRequest, HttpServletResponse)
・doOptions(HttpServletRequest, HttpServletResponse)
・doPost(HttpServletRequest, HttpServletResponse)
・doPut(HttpServletRequest, HttpServletResponse)
・doTrace(HttpServletRequest, HttpServletResponse)
・service(HttpServletRequest, HttpServletResponse)
・service(ServletRequest, ServletResponse)
上記のメソッドで,引数として渡されたjavax.servlet.http.HttpServletResponseのインスタンスに対して,次に示すメソッドの呼出しが無効となります。
- 呼出しが無効となるHttpServletResponseのメソッド
-
・addCookie(Cookie)
・addDateHeader(String, long)
・addHeader(String, String)
・addIntHeader(String, int)
・sendError(int)
・sendError(int, String)
・sendRedirect(String)
・setContentLength(int)
・setContentType(String)
・setDateHeader(String, long)
・setHeader(String, String)
・setIntHeader(String, int)
・setStatus(int)
・setStatus(int, String)
これらのメソッドを実行した場合,指定した値はレスポンスに設定されません。
-
非同期サーブレットでは,HttpServletResponseのインスタンスに対するsendError,setStatusメソッドの呼び出しが無効となるため,ステータスコードの設定はできませんが,非同期サーブレットから上位に例外をthrowした場合は,ステータスコードを500に設定します。
ただし,レスポンスがコミット済みの場合は,すでに返したステータスコードのまま通信を切断します。