15.JSP2.1 Unified ELの高度な使い方
- 4.1. Custom ELResolver
- 4.2. 過去バージョンとのELの互換性
ここでは、より高度なUnified ELの使い方としてCustom ELResolverを取り上げます。
4.1. Custom ELResolver
Unified ELではELResolverクラスがEL式の解決を行っており、 配列、リスト、マップ、JavaBeans、リソースバンドルを取り扱うためのELResolverがそれぞれ定義されています。 さらにELResolverを自身でカスタマイズすることにより、JNDIやJDBCのリソースや独自の暗黙オブジェクトなどの、 標準仕様のELResolverではサポートされていないものについても取り扱うことができるようになります。 ここでは、そのようなCustom ELResolverについて解説します。
Custom ELResolverを導入するには大きく分けて2つのステップが必要です。
- Custom ELResolverクラスの作成
- 作成したELResolverの登録
Custom ELResolverの作成
ELResolverクラスは以下に示す6つのメソッドを持っています。 これらは全て抽象メソッドとなっているので、 Custom ELResolverを作成する際にはこれらのメソッド全てを実装する必要があります。
- getValue(ELContext context, Object base, Object property)
- getType(ELContext context, Object base, Object property)
- isReadOnly(ELContext context, Object base, Object property)
- setValue(ELContext context, Object base, Object property, Object value)
- getCommonPropertyType(ELContext context, Object base)
- getFeatureDescriptors(ELContext context, Object base)
getValueメソッドは指定されたbaseオブジェクト内のpropertyオブジェクトを評価し、その結果を返します。 たとえば #{books.quantity} というEL式では books がbaseオブジェクト、quantity がそのbooks beanのpropertyで、 quantityプロパティの値が返されます。
getValueメソッドでは、式中の属性値を先頭から順にbaseオブジェクト、propertyオブジェクトとして読み込み、評価を行います。 従ってgetValueメソッドは、与えられた式の解決が完了するまで複数回呼び出されることになります。 たとえば ${Color.LightGrey.hex} という式の場合、
呼び出し | base | property |
---|---|---|
1回目 | null | Color |
2回目 | Color | LightGrey |
3回目 | LightGrey | hex |
のように先頭から順に引数として渡されます。 また、毎回の処理が終わったあとはELContextのpropertyResolvedフラグをtrueにします。 こうすると式の解決が他のELResolverに渡されず、そのResolverで処理を続けることができます。
setValueメソッドでは文字通りオブジェクトへの値のセットを行います。 このとき、readOnlyが有効になっている場合にはPropertyNotWritableException等の例外を投げるなどの対処が必要になります。
ELResolverが値の書き込みを取り扱う場合はisReadOnlyメソッドによってフィールドreadOnlyをfalseにします。
getTypeメソッドやgetCommonPropertyTypeメソッド、getFeatureDescriptorsメソッドは Resolverが受け入れるbaseオブジェクトやpropertyオブジェクトの想定されうる最も一般的な型を返します。 式が指し示すオブジェクトやプロパティについての情報を得るために使われます。
このようなCustom ELResolverの例として、 独自の暗黙オブジェクトColorImplicitObjectを定義しそれをEL式から使えるようにした、 ColorELResolverのサンプルコードがこちら にありますので参照ください。 ColorImplicitObjectの説明もこちらにあります。 このColorELResolverを導入すると、たとえば ${Color.LightGrey.hex} というEL式に対してLightGreyという色の16進数コードを返す、 などの処理ができるようになります。
作成したELResolverの登録
作成したELResolverの登録はServletContextListenerで行います。 以下は先ほどのColorELResolverを登録する例です。
・・・ public void contextInitialized(ServletContextEvent servletContextEvent) { ServletContext context = servletContextEvent.getServletContext(); JspApplicationContext jspContext = JspFactory.getDefaultFactory().getJspApplicationContext(context); jspContext.addELResolver(new ColorELResolver()); servletContextEvent.getServletContext().log("ColorELResolver registered"); } ・・・
JSFの場合は、コンフィギュレーションファイルのel-resolver要素で、 作成したELResolverの完全修飾名を指定することにより登録できます。
<el-resolver> webtier-sample.ColorELResolver </el-resolver>
4.2 過去バージョンとのELの互換性
ここではJSPで従来用いられていたUnified EL以前のバージョンのELから 新しいUnified ELへ移行する際の設定変更などについて説明します。
Unified ELに移行するには
JSPでカスタムタグを使っている場合は、TLDをUnified ELに対応するよう変更します。
- <jsp-version>を2.1にする
- <rtexprvalue>を<deferred-value>や<deferred-method>に置き換える
<jsp-version>要素を2.1にアップデートします。 さらに必要に応じて<rtexprvalue>要素を<deferred-value>要素や<deferred-method>要素に置き換えたり、 <rtexprvalue>と<deferred-***>の両方を使うなどして変更します。 後者のように設定すると即時評価式と遅延評価式の両方を受け入れることが可能になります。
JSFのカスタムタグを使っている場合は、 必ず<rtexprvalue>要素を<deferred-value>要素か<deferred-method>要素に置き換えます。 また、JSF1.1以前で使われていたValueBindingクラスやMethodBindingクラスは、 ValueExpressionクラスやMethodExpressioクラスにアップデートする必要があります。
以前のJSPページに "#{ }" が使われていた場合
もし、以前のバージョンのJSPに基づいて作られたページの中に何らかの理由で "#{ }" などの文字列が含まれている場合には エラーがでる可能性があります。 このような場合、以下のようにして "#{ }" という文字列を認識させないようにする回避策が考えられます。
- "\#{" としてエスケープする
- "#{ }"を文字列とみなすようにアプリケーションを設定する
- "#{ }"を文字列とみなすようにJSPページを設定する
"\#{" としてエスケープさせる場合は、
some text \#{ some more text
や
<my:tag someAttribute="sometext\#{moretext" />
などとします。
"#{ }"を文字列とみなすようにアプリケーションを設定する場合、 web.xmlの<jsp-property-group>要素で以下のように宣言します。
<jsp-property-group> <deferred-syntax-allowed-as-literal>true</deferred-syntax-allowed-as-literal> </jsp-property-group>
"#{ }"を文字列とみなすようにJSPページを設定するには、 ページディレクティブを以下のように設定します。
<%@ page ... deferredSyntaxAllowedAsLiteral="true" %>