JSF式言語3.0のガイド

JSF Expression Language 3.0ガイド

1. 概要

この記事では、Expression Languageバージョン3.0(EL 3.0)の最新機能、改善点、互換性の問題について説明します。

これは、この記事の執筆時点での最新バージョンであり、最新のJavaEEアプリケーションサーバーに同梱されています(JBoss EAP 7およびGlassfish 4は、そのサポートを実装した良い例です)。

この記事はEL3.0での開発のみに焦点を当てています。一般的な式言語の詳細については、最初にEL version 2.2の記事をお読みください。

2. 前提条件

この記事に示されている例は、Tomcat 8に対してもテストされています。 EL3.0を使用するには、次の依存関係を追加する必要があります。


    javax.el
    javax.el-api
    3.0.0

このlinkに従うことで、Mavenリポジトリで最新の依存関係をいつでも確認できます。

3. ラムダ式

最新のELイテレーションは、ラムダ式の非常に堅牢なサポートを提供します。 ラムダ式はJava SE 8に導入されましたが、ELでのサポートはJava EE 7に付属しています。

ここでの実装はフル機能を備えており、ELの使用と評価において多くの柔軟性(および暗黙のリスク)を可能にします。

3.1. ラムダEL値式

この機能の基本的な使用により、ラムダ式をEL値式の値型として指定できます。

それから拡張して、Java SEのラムダ式の場合と同じように、複合ステートメントで再利用するためにELのラムダ関数に名前を付けることができます。 複合ラムダ式はセミコロン(;)で区切ることができます。

このスニペットは、関数をcube識別子に割り当てます。この識別子は、すぐに再利用できます。

3.2. ラムダ式をバッキングBeanに渡す

これをもう少し進めましょう。ロジックをEL式に(ラムダとして)カプセル化し、それをJSFバッキングBeanに渡すことで、多くの柔軟性を得ることができます。

これにより、ラムダ式全体をjavax.el.LambdaExpressionのインスタンスとして処理できるようになりました。

public String multiplyValue(LambdaExpression expr){
    return (String) expr.invoke(
      FacesContext.getCurrentInstance().getELContext(), pageCounter);
}

これは、以下を可能にする魅力的な機能です。

  • ロジックをパッケージ化するクリーンな方法であり、非常に柔軟な関数型プログラミングパラダイムを提供します。 上記のバッキングBeanロジックは、さまざまなソースから取得した値に基づいて条件付きにすることができます。

  • アップグレードの準備が整っていない可能性があるJDK 8より前のコードベースでラムダサポートを導入する簡単な方法。

  • 新しいStreams / Collections APIを使用する強力なツール。

4. コレクションAPIの機能強化

ELの以前のバージョンでのコレクションAPIのサポートはやや欠けていました。 EL 3.0はJavaコレクションのサポートにAPIの大幅な改善を導入し、ラムダ式と同様に、EL 3.0はJava EE 7内でJDK 8ストリーミングサポートを提供します。

4.1. 動的コレクションの定義

3.0の新機能として、ELでアドホックデータ構造を動的に定義できるようになりました。

  • リスト:

   
       
           
       
   
  • セット:

   
    ....
   

Note:通常のJavaSets,と同様に、リストされている場合、要素の順序は予測できません。

  • 地図:

   

Tip:動的マップを定義する際の教科書でよくある間違いは、マップキーに一重引用符ではなく二重引用符(“)を使用することです。これにより、ELコンパイルエラーが発生します。

4.2. 高度な収集操作

EL3.0では、ラムダ式のパワー、新しいストリーミングAPI、結合やグループ化などのSQLのような操作を組み合わせた高度なクエリセマンティクスのサポートがあります。 これらは高度なトピックであるため、この記事では取り上げません。 その力を示すためにサンプルを見てみましょう。


    
        
    

上の表は、渡されたラムダ式を使用してバッキングリストをフィルタリングします

 
 

出力テキストavgは、リスト内の数値の平均を計算します。 これらの操作は両方とも、新しいOptional APIによってnullセーフです(以前のバージョンからのもう1つの改善)。

これをサポートするには、JDK 8は必要なく、JavaEE 7 /EL3.0だけが必要です。 これが意味するのは、JDK 8Streamの操作のほとんどをELで実行できるが、バッキングBeanのJavaコードでは実行できないということです。

Tip: JSTL<c:set/>タグを使用して、データ構造をページレベルの変数として宣言し、代わりにJSFページ全体で操作できます。

 

正真正銘のJSFコンポーネントまたはBeanであるかのように、ページ全体で“#{pageLevelNumberList}”を参照できるようになりました。 これにより、ページ全体でかなりの量の再利用が可能になります

5. 静的フィールドとメソッド

ELの以前のバージョンでは、静的フィールド、メソッド、または列挙型アクセスのサポートはありませんでした。 世の中変わったんだよ。

最初に、定数を含むクラスをELコンテキストに手動でインポートする必要があります。 これはできる限り早く行うことが理想的です。 ここでは、JSFマネージドBeanの@PostConstructイニシャライザーでこれを実行しています(ServletContextListenerも実行可能な候補です)。

 @PostConstruct
 public void init() {
     FacesContext.getCurrentInstance()
       .getApplication().addELContextListener(new ELContextListener() {
         @Override
         public void contextCreated(ELContextEvent evt) {
             evt.getELContext().getImportHandler()
              .importClass("com.example.el.controllers.ELSampleBean");
         }
     });
 }

次に、目的のクラスでString定数フィールド(または選択した場合はEnum)を定義します。

public static final String constantField
  = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";

その後、ELの変数にアクセスできます。

 
 

EL 3.0仕様に従って、java.lang.*以外のクラスは、示されているように手動でインポートする必要があります。 クラスで定義された定数がELで使用できるようになるのは、これを行った後です。 インポートは、JSFランタイムの初期化の一部として理想的に行われます。

ここでいくつかのメモが必要です。

  • 構文では、フィールドとメソッドがpublic, static(メソッドの場合はfinal)である必要があります。

  • EL 3.0仕様の最初のドラフトとリリースバージョンの間で構文が変更されました。 そのため、一部の教科書では、次のようなものが見つかる場合があります。

    T(YourClass).yourStaticVariableOrMethod

    これは実際には機能しません(構文を単純化するための設計変更は、実装サイクルの後半で決定されました)

  • リリースされた最終的な構文にはまだバグがありました。これらの最新バージョンを実行することが重要です。

6. 結論

最新のEL実装のハイライトのいくつかを検討しました。 ラムダやストリームの柔軟性などのクールな新機能をAPIにもたらすために、大幅な改善が行われました。

ELには現在の柔軟性があるため、JSFフレームワークの設計目標の1つである、MVCパターンの使用による関心の分離を覚えておくことが重要です。

したがって、APIの最新の改善により、JSFのアンチパターンが可能になる可能性があることに注意してください。これは、ELが以前よりも実際のビジネスロジックを実行できるようになったためです。 したがって、実際の実装では、責任が適切に分離されていることを確認するために、このことを念頭に置くことが重要です。

そしてもちろん、記事can be found on GitHub.からの例