JSFとは何ですか?JavaServerFacesの紹介

JavaServer Faces(JSF)は、コンポーネントベースのイベント指向のWebインターフェイスを構築するためのJava標準テクノロジです。JavaServer Pages(JSP)と同様に、JSFではサーバー側のデータとロジックにアクセスできます。本質的にサーバー側の機能が組み込まれたHTMLページであるJSPとは異なり、JSFは論理ツリー内の正式なコンポーネントを表すXMLドキュメントです。JSFコンポーネントは、HTMLに依存せず、リモートAPIやデータベースへのアクセスを含むすべてのJava機能を備えたJavaオブジェクトによってサポートされています。

JSFのようなフレームワークの重要なアイデアは、HTML、CSS、JavaScriptなどのクライアント側テクノロジをカプセル化(またはラップ)して、開発者がこれらのテクノロジとあまり対話せずにWebインターフェイスを構築できるようにすることです。

この記事では、JavaWebアプリケーションのコンポーネントベースのUI開発に対するJSFのアプローチのスナップショットを示します。簡単な例では、JSFのMVCアーキテクチャ、イベントモデル、およびコンポーネントライブラリを紹介します。例には、JSF 2.3の新機能が含まれ、コンポーネントライブラリにはPrimeFacesを使用します。

進化するJSF

長い間人気があったJSFは、最近、クライアント側のJavaScriptフレームワークを含むJava互換のWebフレームワークとの競争に直面しています。それでも、JavaServer Facesは、特に大規模なJavaエンタープライズ開発では、Java標準のままです。JSF仕様はまた、最近のクライアント側の改善に対応している豊富なフレームワークとライブラリを生み出しました。これらの1つはPrimeFacesであり、このチュートリアルで説明します。

将来の開発のスケジュールは明確ではありませんが、JSF 2.3は、私たちが待つ間、開発者に多くの作業を提供します。2017年3月にリリースされたJSF2.3は、JSFを最新化するために意図的に設計されました。数百の小さな修復と大規模な更新の中で、JSF 2.3は、このチュートリアルの後半で紹介するCDIを優先して、マネージドBeanアノテーションを非推奨にします。

JakartaEEのJSF2.3

2017年9月、オラクルはJavaEEをEclipseFoundationに移行する意向を発表しました。その後、JavaEEはJ​​akartaEEにブランド変更され、JSF 2.3(Eclipse Mojarra)が継続のために採用されました。JSF仕様の次のメジャーリリースはEclipseMojarra3.0です。

JSFでのコンポーネントベースのWebインターフェースの構築

JSFの中心的なアイデアは、機能を再利用可能なコンポーネントにカプセル化することです。これはJSPで使用される再利用可能なタグに似ていますが、JSFコンポーネントはより正式です。

JavaServer Pages内でJSFページを使用できますが、Faceletsを使用してスタンドアロンのJSFページを作成するのが一般的です。フェイスレットは、JSFインターフェースを定義するために設計されたXHTMLページです。Faceletsでは、XMLタグを使用して、JSFユーザーインターフェイスのスキャフォールドとなるコンポーネントツリーを作成します。

リスト1は、Faceletsを使用して記述された単純なJSFページの主要部分を示しています。この例では、CDIを介してスコープに配置されたBeanを介してJavaのサーバー側機能にアクセスしています。CDIについては後で詳しく説明します。

リスト1.JSFサンプルページ

    Hello JavaWorld!   #{javaBean.content}  

リスト1に、標準のXHTMLページを示します。FaceletsビューはXHTMLの上に構築されています。XHTML名前空間に加えて、セカンダリ名前空間が定義および参照されます。

hライブラリーは、JSF HTMLページで使用するための標準的なコンポーネントが含まれています。//xmlns.jcp.org/jsf/htmlライブラリは、この場合には、一般的なHTML要素のコレクションをJSFコンポーネントのコレクションを定義します。これらのコンポーネントの1つは要素です。

JSFのHTMLコンポーネント

構文に関しては、リスト1の要素jsf/htmlh接頭辞付きのライブラリーを参照しています。次に、ライブラリ内の特定のコンポーネント、つまりコンポーネントを参照しheadます。

コンポーネントは、HTMLのhead要素を出力します。(このような単純な目的では、その構文はすべてやり過ぎのように見えるかもしれませんが、すぐにわかるように、それには十分な理由があります。)

コンポーネントのネスト

頭の中には、標準のHTML要素がネストされています。この要素は、その中にネストされたコンテンツの子要素とともに、コンポーネントに提供されます。

ドキュメントの本文には、JSF式が#{}構文に含まれています。これは、次の${}形式のJSP式とまったく同じです。スコープ内のJavaオブジェクトと単純な関数にアクセスできます。

JSFの基本的なパターンは単純です。Faceletsを使用して1つまたは複数のコンポーネントライブラリを参照するXMLツリーを構築し、ライブラリ内のコンポーネントを使用してJavaオブジェクトをHTMLとしてレンダリングします。

JSFでのJavaオブジェクトの使用

リスト1に戻ると、JSF式(${javaBean.contentjavaBean内で、このマークアップが実行されたときにオブジェクトがスコープ内にあることに注意してください。FaceletsのXHTMLは.contentjavaBeanオブジェクトのプロパティにアクセスします。最終的な出力は、Faceletsビュー構造をJavaのサーバー側データおよびロジック機能とマージするWebインターフェースです。

JSF式の使用は、JSFユーザーインターフェイスからJavaアプリケーションデータにアクセスするための1つの方法にすぎません。最終的には、JSFコンポーネントがJavaバックエンドと対話できる他の方法(データリストやグリッド、さまざまな入力コントロールなど)を検討する必要があります。今のところ、JSFがXMLタグ(またはアノテーション)を使用して、Javaオブジェクトに含まれるデータに基づいてHTMLを出力するコンポーネントのツリーを作成する方法を吸収するだけで十分です。

注釈とXML

JSF 2.3では、XMLメタデータを完全に避けて、アノテーションを使用してJSFコンポーネントを定義することが可能になりました。XMLを編集せずに、JSFアプリを定義してデプロイすることは完全に可能です。

JSFアプリケーションの構造

JavaServerPagesやサーブレットAPIと同様に、JavaServerFacesには標準のディレクトリ構造とメタデータが必要です。これらは.warファイルとしてデプロイされます。

.warファイルの構造は、サーブレットまたはJSPアプリケーションに似ています。これに/web-appは、アプリケーションのマークアップファイル(この場合はHTML、JSP、およびフェイスレット)を保持する/WEB-INFディレクトリと、アプリケーションを説明するためのメタデータを提示するディレクトリが含まれています。

JSFにサービスを提供

GlassfishのようなJavaEEコンテナでJSFを実行できますが、本当に必要なのは単純なサーブレットコンテナだけです。Tomcatは、JSFおよびその他のサーバー側Javaテクノロジーの一般的なコンテナーです。

JSF 2.3:仕様と実装

Javaの強みの1つは、標準ベースであり、それらの標準はオープンソースのコミュニティプロセスによって管理されていることです。開始以来、Java Community Process(JCP)はJavaテクノロジの開発を監督してきました。仕様または仕様の改善がJCPによって開発および承認されると、複数の関係者が実装できるようになります。最近まで、サーブレット、JSP、およびJSFはすべて、JCPのオープンソース仕様プロセスを使用して開発されていました。

この記事の執筆時点での最新のJSF仕様は、2017年にJava EE 8の一部としてリリースされたJSF2.3です。Oracle(現在のEclipse)のMojarraはJSFリファレンス実装であり、MyFacesとPrimeFacesは人気のあるサードパーティの実装です。

これらの各フレームワークは、いくつかの標準コンポーネントを含むJSFコアを実装します。ベンダーは、標準に加えて追加のコンポーネントライブラリを提供する場合もあります。JSFフレームワークを評価するときは、アプリケーションのニーズと、アプリケーションの構築に役立つコンポーネントライブラリを検討することをお勧めします。理想的には、JSFフレームワークは、箱から出してすぐに、必要なものにできるだけ近づける必要があります。

JSF2.3のMVC

JSF is an MVC framework, implementing the model-view-controller pattern. In the MVC pattern, the idea is to separate the three concerns of a UI into discreet parts, so they're easier to manage. In general, the view is responsible for displaying data in the model, and the controller is responsible for setting up the model and routing the user to the correct view.

In a JSF implementation, the view is the Facelets page with its set of XML tags. These define the layout of the user interface. The other half of using JSF is the server-side, where Java classes back those UI components.

Managed beans deprecated in JSF 2.3

Managed bean annotations have been deprecated in JSF 2.3, and replaced by CDI (Contexts and Dependency Injection). With CDI, developers define a context and inject objects to that context. Those familiar with managed beans will find the annotation syntax slightly different, but the semantics remain exactly the same.

Controller beans

In JSF 2.3, controller beans provide the controller part of the MVC equation. Normal Java objects (often called POJOs, or plain old Java objects) provide the model.

In terms of process flow, controller beans:

  1. Decide where to direct user requests
  2. Set up POJOs for the model
  3. Use the model to render the Facelets view

JSF then folds together the component tree and model to render the output HTML.

リスト2は、javaBeanCDIを使用してリスト1のオブジェクトを定義する方法を示しています。このリストは、アプリケーションの依存関係にcdi-api-1.2.jarがあることを前提としています。

リスト2.CDIを使用して定義されたJavaBean

 import javax.inject.Named; import javax.enterprise.context.SessionScoped; @Named @ViewScoped public class JavaBean implements Serializable { private String content = ìWelcome to JSF!î // getters/setters } 

PrimeFacesを使用したJSF2.3

次のセクションでは、PrimeFacesを使用して、JSFがMVCパターン、イベント駆動型メッセージング、および再利用可能なコンポーネントを実装する方法を示します。開始するには、PrimeFaces Showcaseを開き、左側の列の[データ]リンクをクリックして、[ DataList ]を選択します。これにより、PrimeFacesのDataListデモコードが表示されます。

図1は、これらのサンプルの場所を示しています。

マシュータイソン

図2は、PrimeFacesDataListデモから取得した単純なデータテーブルの出力を示しています。

マシュータイソン

PrimeFaces DataList:データモデルへのアクセス

Listing 3 presents the markup for this dataList display. If you scroll to the bottom of the PrimeFaces showcase, you can see the markup in the dataList.xhtml tab.

Listing 3. Facelet for PrimeFaces DataList

   Basic  #{car.brand}, #{car.year}  

In Listing 3, notice the value property of the dataList component. You can see that this references a dataListView object, and accesses the .cars1 property on it. The component is going to use the model object returned by that field. JSF tokens use conventional accessors to reference object properties, so .cars1 will refer to the getCars() getter on the object.

Next, notice the var="car" property. This tells the dataList component what variable to use when it iterates over the list of cars returned by the value field. These properties are specific to the dataList component, but the value property is very common. The var attribute is also conventional for components that iterate over lists.

In the body of the component in Listing 3, you can see the car variable is accessed via JSF expressions like #{car.brand}. Each iteration of the dataListView.cars1 instance will output the car.brand field.

Notice that the tag demonstrates the ability to customize components for how they will display. In this case, the header is defined as Basic.

You can see how the Facelets XML will drive this output by combining the data with the markup. Now let's look at the Java code behind it.

DataList's server-side components

Listing 4 shows DataListView, the Java class that is used by the markup in Listing 3. You'll see shortly how the dataListView instance is associated with the DataListView class.

Listing 4. DataListView class

 package org.primefaces.showcase.view.data; import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Named; // Pre JSF 2.3, this was: // import javax.faces.bean.ManagedBean; import javax.inject.Inject; import javax.faces.bean.ViewScoped; import org.primefaces.showcase.domain.Car; import org.primefaces.showcase.service.CarService; @Named @ViewScoped public class DataListView implements Serializable { private List cars1; private Car selectedCar; @Inject("#{carService}") private CarService service; @PostConstruct public void init() { cars1 = service.createCars(10); } public List getCars1() { return cars1; } public void setService(CarService service) { this.service = service; } } 

Listing 4 has a few other important elements, which we'll consider piece by piece.

Dependency injection and annotations

First, notice that the DataListView class is annotated with @Named, which you can see from the import import javax.inject.Named; is part of JSF. The @Named annotation tells JSF this bean is part of the app. The @ViewScoped annotation informs JSF that the bean will live for just the life of the view.

次に、CarServiceプロパティに@Inject注釈があることを確認します(@ManagedPropertyJSF 2.3より前と呼ばれます)。これは、Springフレームワークやその他の依存性注入ツールで普及している手法であるBeanを「相互に接続」できるようにするもう1つのJSF機能です。本質的に、JSFはcarServiceスコープ内のオブジェクトを検索し、それをオブジェクトのserviceフィールドに自動的に関連付けDataListViewます。