javaserver faces 2.3: 次期バージョンの構想 · jsf...

8
ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016 05 //enterprise java / J avaServer Faces(JSF)は、Java EEでのコンポーネントベースのモデル・ ビュー・コントローラ(MVC)フレームワークです。初めてJava EEの一部 になったのは2006年のJava EE 5でしたが、その2年前から単独で使用する ことができました。JSFは、この12年の間で何度か大きく作り直されてきまし た。 最近に至るまでのJSFの歴史 バージョン1.2で、JSF単独のフレームワークからJava EEに統合されまし た。これによって、JSPの互換性にまつわるいくつかの大きな問題が修正さ れ、JSF独自の式言語(EL)が廃止されてJSPが提供する言語が使われるこ とになりました。 2009年のJSF 2.0は、現在に至るまでの最大の進化でした。ポストバック、 ヘビー・ビュー・ステート、リンクのカプセル化(ナビゲーション・ルール)は 重視されなくなり、代わってRESTスタイルの動詞、MVCアクション・パターン の制限付きサポート、ビュー・ステートの小型化(リストア・ビューの概念を 事実上放棄し、代わりにポストバック後のビューをゼロから再構築するこ と)などに主眼が置かれるようになりました。 2013年に登場したJSF 2.2は、JSF 2.0と同じ方向に向かってさらに進化し たものです。完全なステートレス・モードが導入され、ステートはさらに重視 されなくなりました。HTML(と、構文とサーバーサイドのロジックをつなげ る特殊な名前空間属性だけ)を使って直接ページを作成する構文が導入さ れ、コンポーネントへの依存はさらに減りました。また、MVCアクション・パ ターンのサポートも強化されました。 すでに、JSF 2.0のJSFネイティブBean機能はContexts and Dependency Injection(CDI)で透過的に置き換えられていますが、ビュー・スコープなど のいくつかのよく使われるネイティブ機能が残っているため、ネイティブ・マ ネージドBeanを使用し続けている人々もいます。CDIとの連携はJSF 2.2か ら始まりました。具体的には、CDI対応のビュー・スコープが導入され、JSFの 新しいロー・スコープはCDIに直接基づくものになりました。 もしJSFが今作られたものだったとすれば、最初から完全にCDIに基づく ものになっていた可能性が高いでしょう。つまり、現在JSFが提供するほと んどのファクトリやプラグイン・ポイントは、CDI BeanマネージャやCDI拡 張、デコレータに基づいたものになっていたはずです。明らかに、新しいプ ロジェクトではこれが理想的ですが、完全にJSFを再作成しつつ下位互換 性を維持するのは、不可能とは言わないまでも相当困難なことです。JSF( と一般的なJava EE)の美点の1つは、下位互換性が非常に重視されてい ることです。10年前に作られたJSFアプリケーションでも、最新バージョ ンのJava EEでほぼ動作し、完全に動作することも十分あります。そのた め、Java EEは比較的簡単にアップグレードできます。新バージョンのJava EEに移行するために、膨大な事前作業が必要になることはありません。既 存のコードは「そのまま」動作可能です。その間に、新しいAPIを活用できる ようにアプリケーションを徐々に更新すればいいのです。 この歴史に照らし合わせて考えると、JSF 2.3は下位互換性を保ち、以前 の動作に戻すスイッチを提供しつつ、CDIとの連携をさらに進めることにな るでしょう。また、可能な部分でのJava 8の活用、Java EE 7で導入された WebSocketのサポートなど、その他のJava EEサービスが活用されることも 考えられます。 本記事では、リファレンス実装のバージョン2.3マイルストーン6の時点で ほぼ完成している2つの機能について説明します。その1つはコンバータ、バ リデータ、インジェクション、EL解決に関するCDI連携、もう1つはマルチコン ポーネント検証用のBean検証です。さらに、本記事の執筆時点で作業中で あり、まだ完成していない2つの機能も紹介します。その1つは拡張子のない ARJAN TIJMS JavaServer Faces 2.3: 次期バージョンの構想 長年の制限を解消する新機能

Upload: vunguyet

Post on 08-Feb-2019

225 views

Category:

Documents


0 download

TRANSCRIPT

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

05

//enterprise java /

JavaServer Faces(JSF)は、Java EEでのコンポーネントベースのモデル・ビュー・コントローラ(MVC)フレームワークです。初めてJava EEの一部になったのは2006年のJava EE 5でしたが、その2年前から単独で使用することができました。JSFは、この12年の間で何度か大きく作り直されてきました。

最近に至るまでのJSFの歴史バージョン1.2で、JSF単独のフレームワークからJava EEに統合されました。これによって、JSPの互換性にまつわるいくつかの大きな問題が修正され、JSF独自の式言語(EL)が廃止されてJSPが提供する言語が使われることになりました。2009年のJSF 2.0は、現在に至るまでの最大の進化でした。ポストバック、ヘビー・ビュー・ステート、リンクのカプセル化(ナビゲーション・ルール)は重視されなくなり、代わってRESTスタイルの動詞、MVCアクション・パターンの制限付きサポート、ビュー・ステートの小型化(リストア・ビューの概念を事実上放棄し、代わりにポストバック後のビューをゼロから再構築すること)などに主眼が置かれるようになりました。2013年に登場したJSF 2.2は、JSF 2.0と同じ方向に向かってさらに進化したものです。完全なステートレス・モードが導入され、ステートはさらに重視されなくなりました。HTML(と、構文とサーバーサイドのロジックをつなげる特殊な名前空間属性だけ)を使って直接ページを作成する構文が導入され、コンポーネントへの依存はさらに減りました。また、MVCアクション・パターンのサポートも強化されました。すでに、JSF 2.0のJSFネイティブBean機能はContexts and Dependency Injection(CDI)で透過的に置き換えられていますが、ビュー・スコープなどのいくつかのよく使われるネイティブ機能が残っているため、ネイティブ・マ

ネージドBeanを使用し続けている人々もいます。CDIとの連携はJSF 2.2から始まりました。具体的には、CDI対応のビュー・スコープが導入され、JSFの新しいロー・スコープはCDIに直接基づくものになりました。もしJSFが今作られたものだったとすれば、最初から完全にCDIに基づくものになっていた可能性が高いでしょう。つまり、現在JSFが提供するほとんどのファクトリやプラグイン・ポイントは、CDI BeanマネージャやCDI拡張、デコレータに基づいたものになっていたはずです。明らかに、新しいプロジェクトではこれが理想的ですが、完全にJSFを再作成しつつ下位互換性を維持するのは、不可能とは言わないまでも相当困難なことです。JSF(と一般的なJava EE)の美点の1つは、下位互換性が非常に重視されていることです。10年前に作られたJSFアプリケーションでも、最新バージョンのJava EEでほぼ動作し、完全に動作することも十分あります。そのため、Java EEは比較的簡単にアップグレードできます。新バージョンのJava EEに移行するために、膨大な事前作業が必要になることはありません。既存のコードは「そのまま」動作可能です。その間に、新しいAPIを活用できるようにアプリケーションを徐々に更新すればいいのです。この歴史に照らし合わせて考えると、JSF 2.3は下位互換性を保ち、以前の動作に戻すスイッチを提供しつつ、CDIとの連携をさらに進めることになるでしょう。また、可能な部分でのJava 8の活用、Java EE 7で導入されたWebSocketのサポートなど、その他のJava EEサービスが活用されることも考えられます。本記事では、リファレンス実装のバージョン2.3マイルストーン6の時点でほぼ完成している2つの機能について説明します。その1つはコンバータ、バリデータ、インジェクション、EL解決に関するCDI連携、もう1つはマルチコンポーネント検証用のBean検証です。さらに、本記事の執筆時点で作業中であり、まだ完成していない2つの機能も紹介します。その1つは拡張子のない

ARJAN TIJMS

JavaServer Faces 2.3:次期バージョンの構想長年の制限を解消する新機能

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

06

//enterprise java /

URL、もう1つはプログラムとアノテーションベースによる構成です。本記事の内容を理解するためには、Java EEテクノロジーとJSFの概要についての知識が必要です。入門者向けのチュートリアルとなる内容は想定していません。

CDI連携JSF 2.2以降、JSFの多くのアーティファクトで@Injectベースのインジェクションがサポートされています。この機能は、実際にはCDI Beanではないサーブレットが@Injectをサポートする方法にとても似ています。各アプリケーション・サーバー・ベンダーがインジェクション・サービスを提供するためには、あるサービス・プロバイダ・インタフェース(SPI)を実装する必要があります。OracleによるJSFのオープンソース実装であるMojarraでは、com.sun.faces.spi.InjectionProviderインタフェースがSPIにあたります。このアプローチによって、実際のインジェクション・サービスが抽象化されます。このこと自体が有益なこともある一方、この方法には明確な欠点もあります。このインタフェースは非標準であり、JSF実装とJSFを完全にサポートしたいJava EEアプリケーション・サーバーごとに別々に実装する必要がある点です。これはN×Mで増殖するため、自由な実装の組み合わせやマッチングの妨げになる問題です。さらに、CDI機能がサポートできる範囲を大きく制限することにもなります。たとえば、PhaseListenerは@Injectをサポートできますが、スコープをサポートせず、デコレートはできず、インターセプタを含めることもできません。また、一般的にインジェクション・ポイントはCDI拡張で変更できません。JSF 2.3の一部のアーティファクト(コンバータ、バリデータ、ビヘイビア)では、別のアプローチがとられています。このようなアーティファクトには、先ほどのInjectionProviderのような独自のSPIに依存せず、本物のCDI Beanを使用するタイプのものがあります。実際にJSFは、ここでこれらのアーティファクトを取得し、CDIの使用とともに提供されるインジェクションなどのサービスを提供するメカニズムとして、標準化されたBeanManagerを使用します。下位互換性を維持するという目的のため、ネイティブのルックアップとインジェクションの仕組みは保持されます。実際、現在のMojarraは、CDIベースのコンバータに委譲する古いネイティブ・コンバータを内部的に使ってこの新しいタイプのコンバータを透過的にランタイムに統合しています(これは、Java EEでよく見られるトリックです)。

CDIベースのELリゾルバJSF 2.3で、JSF独自の機能がCDIによって置き換えられるもう1つの部分は、暗黙オブジェクトのELリゾルバに関する部分です。暗黙オブジェクトとは、EL経由で使用することができる変数です。たとえば、#{facesContext}、#{request}、#{param}などのFaceletが暗黙オブジェクトにあたります。現在のJSF仕様では、これらのオブジェクトはJSF固有のELリゾルバで解決される必要があると規定されています。しかし、CDIはすでに汎用的なELリゾルバを提供しています。このリゾルバを使うおもなメリットは、特に何もしなくても一定のJSFパフォーマンス改善が可能であることです。CDIリゾルバを使用することによって、JSF独自のリゾルバで同じような改善やチューニングを二重に行う必要がなくなるからです。汎用CDI ELリゾルバは、いわゆるビルトインのBean<T>を利用可能にすることによって動作します。このビルトインのBean<T>には名前(暗黙オブジェクトの名前)と、暗黙オブジェクト自体を生成するcreate()メソッドがあります。EL解決の視点から見てほとんど副作用と言えるのが、Bean<T>を使うことによって、まさにその暗黙オブジェクトもインジェクションできるようになることです。さらに、スコープを設定することもできます。このようなスコープは一種のキャッシュとして機能し、さらなるパフォーマンスの向上に役立つ可能性もあります。ただし、そのスコープに暗黙オブジェクトの寿命が正確に反映されるように注意する必要があります。次のコードは、Bean<T>のビルダーの例です。

public class HeaderValuesMapProducer extends

CdiProducer<Map<String, String[]>> {

public HeaderValuesMapProducer() {

super.name("headerValues")

.scope(RequestScoped.class)

.qualifiers(

new HeaderValuesMapAnnotationLiteral())

.types(

new ParameterizedTypeImpl(

Map.class,

new Type[]{String.class,

String[].class}),

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

07

//enterprise java /

Map.class,

Object.class)

.beanClass(Map.class)

.create(e ->

FacesContext.getCurrentInstance()

.getExternalContext()

.getRequestHeaderValuesMap());

}

}

マルチコンポーネント検証JSFなどのWebフレームワークを使用する1つの重要な理由は、クライアントから送信されるデータを検証する、明確に定義された機能が提供されることです。JSFでは、ネイティブのバリデータをソース・サイド(テキスト入力などのコンポーネント)にアタッチするか、Bean検証制約をターゲット・サイド(バッキングBeanプロパティ)にアタッチするかのいずれかによって検証を実行します。いずれの場合も、検証の対象は単一のコンポーネントから送信される入力のみになります。この方式は、パスワードが少なくとも8文字であることを検証する場合にはうまく動作しますが、メインの入力フィールドのパスワードが確認用の入力フィールドのものと同じでなければならないという要件には利用できません。マルチコンポーネント検証のニーズはかなり前から認識されていました。実際、JSFに公式に提出された最初の問題は、まさにこの機能を求めるものでした。歴史的には、この問題は特別なコンポーネント(たとえば、1つはメイン・エントリ用、もう1つは確認用の2つの入力フィールドを持つ1つのコンポーネント)を作成したうえで、OmniFacesなどのユーティリティ・ライブラリの特殊なマルチコンポーネント・バリデータを使用するか、単にアクション・メソッドで手動により検証するという方法で解決されていました。現在に至るまで、この基本的な問題が根本的なレベルで対処されることはありませんでした。JSF 2.3では、初めてこの問題の解決に向けた試みがなされています。ここでも、既存のプラットフォーム・サービスを活用するというアプローチがとられています。すなわち、クラスレベルのBean検証の活用です。ここでの考え方は、特殊な制約バリデータをバッキングBeanにアタッチするというものです。それぞれのBean検証ルールについて、このア

タッチが発生します。最初に特殊なアノテーションを定義します。次にConstraintValidatorの実装を定義し、アノテーションの属性を使ってそのアノテーションをConstraintValidatorにリンクさせます。最後に、そのアノテーションをバッキングBeanに付加します。以下のコードにその例を示します。

@Named @RequestScoped

@ValidIndexBean(groups =

java.util.RandomAccess.class)

public class IndexBean implements

ConstraintValidator<ValidIndexBean, IndexBean> {

@Constraint(validatedBy = IndexBean.class)

@Target(TYPE) @Retention(RUNTIME)

public @interface ValidIndexBean {

String message() default "Invalid Bean";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default{};

}

public void initialize(

ValidIndexBean constraintAnnotation) {}

public boolean isValid(

IndexBean other,

ConstraintValidatorContext context) {

return other.getFoo().equals(other.getBar());

}

@NotNull

private String foo;

@NotNull

private String bar;

// + getters/setters

}

さまざまなBeanの各種フィールドに適用できる@Emailなどの再利用可能なバリデータを作るためであれば、このような作業を行う価値があるでし

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

08

//enterprise java /

ょう。しかし、バッキングBean用のマルチコンポーネント検証は、多くの場合にその場限りの用途になります。単一のBeanに一度だけ使うことを考えると、この方法は可動部分が多すぎると言えるかもしれません。これに代わる方法として、もう少し再利用しやすいバリデータのライブラリを作成することができます。たとえば、OmniFacesのマルチコンポーネント・バリデータのBean検証に対応するvalidateEqual、validateOneOrMore、validateOneOrNoneなどです。先ほどのサンプルと比較するため、EL対応の属性を使用した再利用可能なvalidateEqualバリデータで検証対象となるBeanプロパティを指定する例を紹介します。この目的でELを使用しているのは単なる例であり、実際には、プロパティをアノテーションでマークするなどの別の用途に使用できることに注意してください。この例では、まず個別に検証アノテーションを定義します。

@Constraint(validatedBy = ValidateEqualValidator.

class)

@Target(TYPE) @Retention(RUNTIME)

public @interface ValidateEqual {

String message() default "Invalid Bean";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

String[] inputs();

}

属性inputsが増えていることに注意してください。

次に、実際のバリデータを定義できます。

public class ValidateEqualValidator implements

ConstraintValidator<ValidateEqual, Object> {

private List<String> inputs;

public void

initialize(ValidateEqual constraintAnnotation) {

this.inputs =

asList(constraintAnnotation.inputs());

}

public boolean

isValid(Object bean,

ConstraintValidatorContext ctx) {

return new

HashSet<>(collectValues(bean, inputs))

.size() == 1;

}

}

このバリデータでは、プラットフォームが提供するEL 3.0仕様のELProcessorを使うことで、検証対象となるBeanからプロパティ値を簡単に取り出すことができます。これは次のようにして実行します。public static List<Object> collectValues(Object bean) {

ELProcessor elProcessor = getElProcessor(bean);

return inputs.stream()

.map(input -> elProcessor.eval(input))

.collect(toList());

}

単に新しいインスタンスを作成してCDI BeanマネージャからELResolverに渡すだけで、完全に機能するELProcessorを取得してJava EE環境で使用することができます。これは次のようにして実行できます。

public static ELProcessor getElProcessor(Object bean) {

ELProcessor elProcessor = new ELProcessor();

elProcessor.getELManager()

.addELResolver(

CDI.current()

.getBeanManager()

.getELResolver());

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

09

//enterprise java /

elProcessor.defineBean("this", bean);

return elProcessor;

}

ここで特に注目すべき点は、getElProcessor()メソッドの中で、ELProcessorコンテキストに"this" という名前で検証対象となるBeanを追加している部分です。このアプローチは、検証すべきプロパティを後ほど定義する場合に使用します(補足:ここでは、JSF、Bean検証、EL、CDIという4つの異なるJava EE仕様がかなりシームレスに使われていることに注目してみると面白いかもしれません)。最後に、再びバッキングBeanにアノテーションを付加します。ただし、今回は再利用可能なバリデータを使います。@Named@RequestScoped@ValidateEqual( groups = RandomAccess.class, inputs={"this.foo", "this.bar"})public class IndexBean { @NotNull private String foo; @NotNull private String bar; // + getter/setters}

ここでは、一緒に検証を行う2つのプロパティへのEL参照によってinputs 属性が初期化されていることに注目してください。いずれの場合でも、実際の入力コンポーネントを含むFaceletの一部は次のようになります。

01 <h:form>

02 <h:inputText value="#{indexBean.foo}">

03 <f:validateBean validationGroups =

04 "javax.validation.groups.Default,

05 java.util.RandomAccess" />

06 </h:inputText>

07

08 <h:inputText value="#{indexBean.bar}">

09 <f:validateBean validationGroups =

10 "javax.validation.groups.Default,

11 java.util.RandomAccess" />

12 </h:inputText>

13

14 <f:validateWholeBean value="#{indexBean}"

15 validationGroups="java.util.RandomAccess"/>

16

17 <h:commandButton value="submit" />

18 </h:form>

【編集注:スペースの制約上、4行目と5行目、10行目と11行目は折り返されていますが、1行で入力する必要があります。】JSFと組み合わせたフル・クラスBean検証のかなり重要な側面は、バリデータが参照するBeanはバッキングBeanのコピーであり、実際のバッキングBeanではないことにあります。この理由は、JSFの検証セマンティックスでは、何らかの検証や変換が失敗した場合に、モデル(バッキングBean)が更新されてはならないためです。しかし、フル・クラスBean検証が実行されるのは、Beanが完全に更新されてからです。この不整合を防ぐために、まずランタイムがバッキングBeanのコピーを作成し、そのコピーを更新してから検証を行います。すべての検証の制約に合格した場合にのみ、実際のバッキングBeanが更新されます。

拡張子のないURL内部的には、JSFはFacesServletと呼ばれるサーブレットで実装されています。このサーブレットは、特定のパターンのリクエストをリスニングします。デフォルトで、"/faces/*"、"*.jsf"、"*.faces"がこのパターンに該当し、JSF 2.3では"*.xhtml"も含まれます。ユーザーは、サーブレットをURLパターンにマッピングするために使用するものと同じサーブレット構文を使って、web.xmlに独自のパターンを設定することができます。前述の情報からわかるように、パス・マッピングと拡張子マッピングの両方がサポートされています。パス・マッピングの例はhttp://example.com/faces/page.xhtml、拡張子マッピングの例はhttp://example.com/page.jsfです。最新のWebアプリケーションでは、「クリーン」なURL、具体的には拡張

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

10

//enterprise java /

子がなく通常は煩雑な情報が付いていないURLが好まれます。残念ながら、JSFではすぐにこのようなURLをサポートすることはできません。不思議なことに、先ほどの例のように、パス・マッピングを使用する場合でも拡張子が必要です。PrettyFacesやOmniFacesなどのサードパーティ・ライブラリを使用することで、JSFでクリーンなURLを実現できます。ただし、現時点においてこの種の機能は十分よく理解されていて成熟もしていると考えられるため、JSF自体に含めるのがふさわしいものです。JSF 2.3では、拡張子のないURLに関して次の3点を目標としています。まず、パス・マッピングを拡張子なしで動作させることです。たとえば、http://example.com/faces/pageのようなURLをすぐに使えるようにします。次に、完全一致マッピングの正式サポートです。たとえば、web.xmlに次のようなマッピングがある場合、http://example.com/page shoのようなURLが動作するようにします。

<servlet>

<servlet-name>Faces Servlet</servlet-name>

<servlet-class>

javax.faces.webapp.FacesServlet

</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>Faces Servlet</servlet-name>

<url-pattern>/page</url-pattern>

</servlet-mapping>

最後に、この目標でもっとも難易度が高いものになりますが、ユーザーが完全一致マッピングを使って明示的に/page(やその他のページ)にマッピングしなくても、1つの構成オプションを設定するだけでhttp://example.com/page のようなURLが動作するようにします。本記事の入稿時点では、この3番目の目標をどのように実現するかについて、明確には決まっていません。しかし、考えられるアプローチは、ResourceHandlerに新しいlistViewResources()メソッドを追加し、アプリケーションの起動時にServlet 3.0仕様のプログラムに

よるマッピングを活用して、指定されたResourceHandlerで処理されるすべてのビュー・リソース(Faceletsなど)に自動的に完全一致マッピングを追加することです。

プログラムとアノテーションベースによる構成JSFで高レベルの宣言的な構成を行うためには、web.xmlのコンテキスト・パラメータまたは専用のfaces-config.xmlファイルのいずれかを使用します。さらに、Applicationクラスによる構成、コールバックとXML Document Object Model (DOM) APIを使ってfaces-config.xmlファイルの内容を渡し、プログラムから行う構成など、いくつかの低レベルなオプションも利用できます。特に、web.xmlのコンテキスト・パラメータには、参照しなければならない単なる文字列(通常は長い文字列)で構成され、スペルミスが起きやすいという欠点があります。さらに、ある構成アイテムのデフォルトが何であるかも直接確認することはできません。web.xmlを使う方法と、.warファイルのWEB-INFフォルダにあるfaces-

config.xmlファイルを使う方法は、いずれもJava EE起動プロセスの初期段階で起動するCDI拡張やその他のアーティファクトから読み込むことができないという欠点を共有しています。また、XMLベースのファイル(いわゆるデプロイメント・ディスクリプタ)は柔軟性が特に高いわけではありません。というのも、Java EEには、ファイルへのプレースホルダの配置や、ファイルの条件付きインクルード、オーバーレイを行うプラットフォーム全体を対象にしたサービスはありません。このような問題があるため、JSFでアノテーションベースの高レベルな構成システムを提供し、オプションとしてプログラムからも構成を行えるようにすることが計画されています。このような構成のもっとも基本的な形式は、次のようなものになります。

@FacesConfigpublic class SomeClass {

}

この構成を行うだけで、JSFサーブレット・マッピングが自動的に追加されます。現在は、空の(ただし有効な)faces-config.xmlファイルが存在する場合や、アプリケーション内のいずれかのクラスに廃止され

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

11

//enterprise java /

た@ManagedBeanアノテーションが見つかった場合などにこの動作が実行されます。.前述のコンテキスト・パラメータの代替方法として、@FacesConfigア

ノテーションの属性を使用してJSFのさまざまな機能を構成することもできます。@FacesConfig(

stateSavingMethod = Server,

faceletsRefreshPeriod = -1,

projectStage = Production

)

public class SomeClass {

}

ここでの目的は、可能な場合は強く型付けされた値を使用することです。たとえば、Serverの値を列挙型にすることもできるでしょう。現時点ではまだ検討中ですが、先ほどのバリデータの例と同じようなEL対応の属性を使ったプログラム的な側面も追加される可能性があります。次の例をご覧ください。

@FacesConfig(

stateSavingMethod = Server,

faceletsRefreshPeriodExpr =

"this.faceletsRefreshPeriod",

projectStageExpr = "configBean.dev?

'Development' : 'Production'"

)

public class SomeClass {

int getFaceletsRefreshPeriod() {

return … ? -1 : 0;

}

}

この例では、アノテーションが付加されたBeanのプロパティを直接参照する式によってfaceletsRefreshPeriodを設定しています。この

プロパティのgetterメソッドの内部では、任意のロジックを使用して希望する結果を決めることができます。一方で、projectStageにはEL内でロジックを直接実行する式が設定されています。このようなEL式は大変複雑になる場合がありますが、できるだけシンプルなものにするよう心がけるとよいでしょう。なお、CDI拡張によって読み込む必要がある属性では、"this"以外のBeanの参照はサポートされていない可能性があります。

まとめJSF 2.3は、Java EEプラットフォームの既存のサービスを使用し、ギャップを埋める必要がある場所で接着剤の役割を果たすコードを提供することによって進化を続けています。今回おもに取り上げたテーマだけでなく、JSFを最新に保ち、さらに簡単に使えるようにするさまざまな機能が導入される予定です。本記事で紹介したものは現在開発中の機能であり、JSF 2.3の最終リリースまでに変更される可能性もあります。各機能についてのさらに詳しい情報や、その他のJSF 2.3の機能については、筆者のブログをご覧ください。 </article>

Arjan Tijms:JSF(JSR 372)とJava EE Security API(JSR 375)の専門家グループのメンバー。2015 Duke’s Choice Awardを受賞したJSF用の有名なOmniFacesライブラリの作成者の1人であり、複数のJava EEベンダーが使用しているJava EE認証サービス・プロバイダ・インタフェース(JASPIC)のテスト・スイート作成の主担当を務めました。[編集注:本号のJASPICの記事をご覧ください。]Tijms氏は、オランダのライデン大学でコンピュータ・サイエンスの理学修士号を取得しています。

ORACLE.COM/JAVAMAGAZINE /////////////////////////////// JULY/AUGUST 2016

12

//enterprise java /

The author’s blog on JSF 2.3 updatesThe official JSF 2.3 JSR

learn more

ATMs, Smartcards, POS Terminals, Blu-ray Players,

Set Top Boxes, Multifunction Printers, PCs, Servers,

Routers, Switches, Parking Meters, Smart Meters,

Lottery Systems, Airplane Systems, IoT Gateways,

Programmable Logic Controllers, Optical Sensors,

Wireless M2M Modules, Access Control Systems,

Medical Devices, Building Controls, Automobiles…

#1 Development Platform

13 BillionDevices Run Java