JavaServer Faces 2.x入門

JavaServer Faces (JSF)は、Java Webアプリケーション用のユーザー・インタフェース(UI)フレームワークです。これは、Javaアプリケーション・サーバー上で実行され、UIをターゲット・クライアントにレンダリングするアプリケーションの記述と維持にかかる負荷を大幅に軽減するように設計されています。JSFは、次のような方法で使いやすさを実現します。

  • 再利用可能なUIコンポーネントのセットからUIを簡単に構築できる
  • UIとの間でアプリケーション・データの移行を簡素化
  • サーバー・リクエスト間でのUIの状態管理を支援
  • クライアントが生成したイベントをサーバー側アプリケーション・コードに記述するための簡易モデルを提供
  • カスタムUIコンポーネントを簡単にビルドして再利用できる

JSFフレームワークの詳細は、Java EE 7チュートリアル、第12章のJavaServer Facesテクノロジを使用した開発を参照してください。

このチュートリアルでは、NetBeans IDEを使用してJSF 2.xサポートをWebアプリケーションに適用する方法を説明します。最初にJSF 2.xフレームワーク・サポートを基本的なWebアプリケーションに追加してから、次のタスクの実行に進みます。

  • リクエスト・データを処理するJSF管理対象Beanの作成
  • 管理対象BeanをアプリケーションのWebページに記述
  • WebページをFaceletsテンプレート・ファイルに変換

NetBeans IDEは、JavaServer Facesのサポートを長期にわたって提供してきました。JSF 2.0およびJava EE 6のリリース以降、NetBeans IDEはJSF 2.0およびJSF 2.1のサポートを提供してきました。詳細は、NetBeans IDEでのJSF 2.xのサポートを参照してください。

内容

このページの内容は、NetBeans IDE 7.2、7.3および7.4に適用されます

このチュートリアルを完了するには、次のソフトウェアとリソースが必要です。

ソフトウェアまたはリソース 必須バージョン
NetBeans IDE 7.1、7.2、7.3、7.4、Java EEバンドル版
Java Development Kit (JDK) 6または7
GlassFishサーバー Open Source Edition 3.xまたは4
jsfDemo Webアプリケーション・プロジェクト 該当なし

注意:

  • NetBeans IDEのJavaバンドル版には、このチュートリアルに必要な、Java EE準拠サーバーのGlassFishサーバーも含まれています。
  • プロジェクトを、正常に機能するソリューションと比較するには、完成したサンプル・プロジェクトをダウンロードします。

WebアプリケーションへのJSF 2.xサポートの追加

まず、IDEでjsfDemo Webアプリケーション・プロジェクトを開きます。IDEでプロジェクトが開いたら、プロジェクトの「プロパティ」ウィンドウを使用して、フレームワーク・サポートを追加できます。

IDEで、JSF 2.xをサポートする新しいプロジェクトを作成することもできます。詳細は、JSF 2.xサポートを含む新しいプロジェクトの作成を参照してください。

  1. IDEのメイン・ツールバーで「プロジェクトを開く」(「プロジェクトを開く」ボタン)ボタンをクリックするか、[Ctrl]-[Shift]-[O] (Macの場合は[⌘]-[Shift]-[O])を押します。
  2. 「プロジェクトを開く」ダイアログで、展開したチュートリアル・プロジェクトを格納した場所に移動します。選択して「プロジェクトを開く」をクリックし、IDEで開きます。

    注意:IDEのインストール時にJUnitプラグインをインストールしていない場合は、NetBeansプロジェクトを開くときにJUnitライブラリへの参照を解決するよう求められることがあります。

  3. プロジェクトを実行して、ブラウザでどのように表示されるかを確認します。「プロジェクト」ウィンドウで「jsfDemo」プロジェクト・ノードを右クリックして「実行」を選択するか、メイン・ツールバーの「プロジェクトの実行」(「プロジェクトの実行」ボタン)ボタンをクリックします。プロジェクトがパッケージ化されてGlassFishサーバーにデプロイされ、ブラウザが開いて開始ページ(index.xhtml)が表示されます。
    ブラウザの開始ページのスクリーンショット
  4. 「送信」ボタンをクリックします。レスポンス・ページ(response.xhtml)が次のように表示されます。
    ブラウザに表示されたレスポンス・ページのスクリーンショット

    現在、開始ページとレスポンス・ページは静的なページで、stylesheet.cssファイルとduke.pngイメージがあり、ブラウザからアクセスできる唯一のアプリケーション・ファイルです。

  5. 「プロジェクト」ウィンドウ([Ctrl]-[1]、Macの場合は[⌘]-[1])で、プロジェクト・ノードを右クリックし、「プロパティ」を選択して、「プロジェクト・プロパティ」ウィンドウを開きます。
  6. 「フレームワーク」カテゴリを選択し、「追加」ボタンをクリックします。
  7. 「フレームワークの追加」ダイアログ・ボックスで、「JavaServer Faces」を選択します。「OK」をクリックします。
    「プロジェクト・プロパティ」ウィンドウ: 「フレームワークの追加」ダイアログ

    JavaServer Facesを選択すると、様々な構成オプションが使用可能になります。「ライブラリ」タブで、プロジェクトがJSF 2.xライブラリにアクセスする方法を指定できます。使用可能なJSFバージョンは、IDEとGlassFishサーバーのバージョンによって異なります。デフォルト・オプションでは、サーバー(GlassFishサーバー)に含まれているライブラリを使用します。ただし、IDEではJSF 2.xライブラリもバンドルされます。プロジェクトで登録されているライブラリを使用する場合は、「登録されているライブラリ」オプションを選択できます。

    JSF構成設定: 「ライブラリ」タブ
  8. 「構成」タブをクリックします。Facesサーブレットをプロジェクトのデプロイメント・ディスクリプタにどのように登録するかを指定できます。また、プロジェクトでFaceletsまたはJSPページを使用するかどうかを示すこともできます。
    JSF構成設定: 「構成」タブ

    プロジェクトで使用する様々なJSFコンポーネント・スイートを「コンポーネント」タブで簡単に構成することもできます。コンポーネント・スイートを使用するには、必要なライブラリをダウンロードし、Antライブラリ・マネージャを使用して、コンポーネント・スイートのライブラリを含む新しいライブラリを作成する必要があります。

    JSF構成設定: 「構成」タブ

    注意:JSFの「コンポーネント」タブは、NetBeans IDE 7.0では使用できません。

  9. 「OK」をクリックして変更を確定し、「プロジェクト・プロパティ」ウィンドウを終了します。

プロジェクトにJSFサポートを追加すると、プロジェクトのweb.xmlデプロイメント・ディスクリプタが変更されて次のようになります。変更場所は太字で示されています。

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

重要: 例に示すように、web.xml<welcome-file>エントリが1つのみ含まれ、このエントリに'faces/'が含まれていることを確認します。これにより、プロジェクトの開始ページ(index.xhtml)が、Facesサーブレットを介してブラウザに表示されるようになります。Faceletsタグ・ライブラリ・コンポーネントが正しくレンダリングされるようにするには、この処理が必要です。

Facesサーブレットがプロジェクトに登録され、index.xhtml開始ページをリクエストすると、ページはFacesサーブレットを介して渡されるようになります。また、PROJECT_STAGEコンテキスト・パラメータのエントリも追加されています。このパラメータを「Development」に設定すると、アプリケーションをデバッグするときに有用な情報が提供されます。参照: 詳細は、http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2

JSFライブラリを見つけるには、「プロジェクト」ウィンドウでプロジェクトの「ライブラリ」ノードを展開します。GlassFish Server 3.1.2またはGlassFish Server 4に含まれているデフォルトのライブラリを使用している場合、これは「GlassFish Server」ノードに表示されるjavax.faces.jarです。(古いバージョンのGlassFishを使用している場合は、jsf-api.jarおよびjsf-impl.jarライブラリがjavax.faces.jarのかわりに表示されます。)

IDEのJSF 2.xサポートには、主にJSF固有の多数のウィザード、およびFaceletsエディタで提供される特別な機能が含まれています。これらの機能については、以降の手順で説明します。詳細は、NetBeans IDEでのJSF 2.xのサポートを参照してください。

管理対象Beanの作成

JSFの管理対象Beanを使用して、ユーザー・データを処理し、リクエスト間でそれを保持することができます。管理対象Beanは、データの格納に使用できるPOJO (プレーン・オールドJavaオブジェクト)です。これは、JSFフレームワークを使用してGlassFishサーバーなどのコンテナで管理されます。

POJOは基本的に、publicで引数のないコンストラクタを格納し、プロパティがJavaBeans命名規則に準拠するJavaクラスです。

プロジェクトを実行して生成された静的ページを見ると、ユーザーが入力した数値が現在選択されている数値と一致するかどうか、また、この結果に適した表示が返されるかどうかを判断する機構が必要です。IDEの管理対象Beanウィザードを使用して、この目的に応じた管理対象Beanを作成します。次の項で作成するFaceletsページは、ユーザーが入力する数値と生成されたレスポンスにアクセスする必要があります。これを有効にするには、userNumberおよびresponseプロパティを管理対象Beanに追加します。

管理対象Beanウィザードの使用

  1. 「プロジェクト」ウィンドウで「jsfDemo」プロジェクト・ノードを右クリックし、「新規」>「JSF管理対象Bean」を選択します。(「管理対象Bean」が表示されない場合は、「その他」を選択します。次に、「JavaServer Faces」カテゴリから「JSF管理対象Bean」オプションを選択します。「次」をクリックします。)
  2. ウィザードで、次の情報を入力します。
    • クラス名: UserNumberBean
    • パッケージ: guessNumber
    • 名前: UserNumberBean
    • スコープ: session
    JSF管理対象Beanウィザード
  3. 「終了」をクリックします。UserNumberBeanクラスが生成され、エディタで開かれます。次の注釈(太字で表示)を確認します。
    package guessNumber;
    
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    
    /**
     *
     * @author nbuser
     */
    @ManagedBean(name="UserNumberBean")
    @SessionScoped
    public class UserNumberBean {
    
        /** Creates a new instance of UserNumberBean */
        public UserNumberBean() {
        }
    
    }

    ここではJSF 2.xを使用しているため、注釈を使用して、JSF固有のコンポーネントをすべて宣言できます。以前のバージョンでは、Faces構成ファイル(faces-config.xml)で宣言する必要がありました。

    すべてのJSF 2.1注釈を確認するには、Faces管理対象Beanの注釈の仕様を参照してください。

コンストラクタの作成

UserNumberBeanコンストラクタは、0から10の間のランダムな数値を生成し、インスタンス変数に格納します。これが、アプリケーションのビジネス・ロジックの一部を形成します。

  1. UserNumberBeanクラスのコンストラクタを定義します。次のコードを入力します(変更箇所は太字で表示)。
    public class UserNumberBean {
    
        Integer randomInt;
    
        /** Creates a new instance of UserNumberBean */
        public UserNumberBean() {
            Random randomGR = new Random();
            randomInt = new Integer(randomGR.nextInt(10));
            System.out.println("Duke's number: " + randomInt);
        }
    
    }

    このコードは0から10の間のランダムな数値を生成し、その数値をサーバー・ログに出力します。

  2. インポートを修正します。そのためには、エディタの左マージンに表示されるヒント・バッチ(ヒント・バッジ)をクリックし、java.util.Randomをクラスにインポートするオプションを選択します。
  3. プロジェクトを再度実行します(「プロジェクトの実行」(「プロジェクトの実行」ボタン)ボタンをクリックするか、[F6] (Macの場合は[fn]-[F6])を押します)。プロジェクトを実行すると、サーバーのログ・ファイルが「出力」ウィンドウに自動的に開かれます。
    「出力」ウィンドウのサーバーのログ

    コンストラクタで示されるように、出力にはDuke's number: が表示されません。UserNumberBeanオブジェクトは作成されませんでした。これは、JSFがデフォルトで遅延インスタンス化を使用するためです。つまり、特定のスコープ内のBeansは、アプリケーションで必要とされたときにのみ作成され、インスタンス化されます。

    @ManagedBean注釈用のJavadocには、次のように記載されています。

    eager()属性の値がtrueで、managed-bean-scopeの値がapplicationの場合は、アプリケーションの開始時にランタイムがこのクラスをインスタンス化する必要があります。このインスタンス化とインスタンスの格納は、他のリクエストを処理する前に実行される必要があります。eagerの値が指定されていないかfalseの場合、またはmanaged-bean-scopeがapplication以外の場合は、デフォルトの「遅延」インスタンス化と管理対象Beanのスコープ指定記憶域が生じます。
  4. UserNumberBeanはセッション・スコープ指定されているため、Serializableインタフェースを実装させます。
    @ManagedBean(name="UserNumberBean")
    @SessionScoped
    public class UserNumberBean implements Serializable {
    ヒント・バッジ(ヒント・バッジ)を使用して、java.io.Serializableをクラスにインポートします。

プロパティの追加

次の項で作成するFaceletsページは、ユーザーが入力する数値と生成されたレスポンスにアクセスする必要があります。これを容易にするため、userNumberおよびresponseプロパティをクラスに追加します。

  1. まず、userNumberという名前のIntegerを宣言します。
    @ManagedBean(name="UserNumberBean")
    @SessionScoped
    public class UserNumberBean implements Serializable {
    
        Integer randomInt;
        Integer userNumber;
  2. エディタ内で右クリックし、「コードを挿入」を選択します([Alt]-[Insert]、Macの場合は[Ctrl]-[I])。取得メソッドおよび設定メソッドを選択します。
    コードのポップアップ・ウィンドウの生成
  3. userNumber: Integer」オプションを選択します。「生成」をクリックします。
    「取得メソッドおよび設定メソッドの生成」ダイアログ

    getUserNumber()およびsetUserNumber(Integer userNumber)メソッドがクラスに追加されます。

  4. responseプロパティを作成します。responseという名前のStringを宣言します。
    @ManagedBean(name="UserNumberBean")
    @SessionScoped
    public class UserNumberBean implements Serializable {
    
        Integer randomInt;
        Integer userNumber;
        String response;
  5. responseの取得メソッドを作成します。(このアプリケーションでは設定メソッドは必要ありません。)前出のステップ2で示したIDEの「コードを生成」ポップアップを使用して、テンプレート・コードを生成することもできます。ただし、このチュートリアルでは、単純に次のメソッドをクラスに貼り付けます。
    public String getResponse() {
        if ((userNumber != null) && (userNumber.compareTo(randomInt) == 0)) {
    
            //invalidate user session
            FacesContext context = FacesContext.getCurrentInstance();
            HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
            session.invalidate();
    
            return "Yay! You got it!";
        } else {
    
            return "<p>Sorry, " + userNumber + " isn't it.</p>"
                    + "<p>Guess again...</p>";
        }
    }
    このメソッドでは2つの関数が実行されます。
    1. ユーザーが入力した数値(userNumber)がセッション用に生成されたランダムな数値(randomInt)と等しいかどうか、およびStringレスポンスが返されるかどうかがテストされます。
    2. ユーザーが正しい数値を推測した場合(たとえばuserNumberrandomIntが正しい場合)、ユーザー・セッションは無効化されます。ユーザーが再度操作する場合に新しい数値が生成されるようにするには、この処理が必要です。
  6. エディタを右クリックし、「インポートを修正」を選択します([Alt]-[Shift]-[I]、Macの場合は[⌘]-[Shift]-[I])。次の項目用に、インポート文が自動的に作成されます。
    • javax.servlet.http.HttpSession
    • javax.faces.context.FacesContext

    エディタ内の項目上で[Ctrl]-[Space]を押すと、コード補完による候補とドキュメント・サポートを呼出しできます。FacesContextで[Ctrl]-[Space]を押して、Javadocのクラス説明を表示します。


    ドキュメントのポップアップ・ウィンドウ
    ドキュメント・ウィンドウの「Webブラウザ」(「Webブラウザ」アイコン)アイコンをクリックし、外部WebブラウザでJavadocを開きます。

ページへの管理対象Beanの接続

JSFの主な目的の1つは、POJOおよびPOJOとアプリケーションのビューとの相互作用を管理するために、ボイラープレート・コードを記述する必要性を除去することです。前の項で、アプリケーションを実行したときにJSFがUserNumberBeanオブジェクトをインスタンス化したのがこの例です。この概念は制御の反転 (IoC)と呼ばれ、コンテナがアプリケーションの一部を管理できるようにするものです。これがない場合、開発者は反復的なコードを記述する必要があります。

前の項では、0から10の間のランダムな数値を生成する管理対象Beanを作成しました。また、ユーザーが入力する数値を表すuserNumberプロパティと、ユーザーの推測に対するレスポンスを表すresponseプロパティも作成しました。

この項では、UserNumberBeanとそのプロパティをWebページで使用する方法について説明します。JSFでは、式言語(EL)を使用して実行できます。式言語を使用して、アプリケーションのWebページに含まれているJSFのUIコンポーネントにプロパティ値をバインドします。この項では、JSF 2.xの暗黙的なナビゲーション機能を活用してindexページとresponseページとの間を移動する方法も説明します。

IDEには、エディタ内の項目上で[Ctrl]-[Space]を押すことによって呼出しできる、コード補完とドキュメント機能によるサポートも用意されています。

まずindex.xhtmlを変更してから、response.xhtmlを変更します。両方のページで、HTMLフォーム要素を、JSF HTMLタグ・ライブラリで定義されているJSFの対応する要素で置き換えます。次に、JSF式言語を使用して、プロパティ値と選択したUIコンポーネントをバインドします。

index.xhtml

  1. エディタでindex.xhtmlページを開きます。「プロジェクト」ウィンドウで「index.xhtml」ノードをダブルクリックするか、[Alt]-[Shift]-[O]を押して「ファイルに移動」ダイアログを使用します。

    indexページとresponseページの両方に、ここで必要なJSF UIコンポーネントがすでに含まれています。それらをコメント解除し、現在使用しているHTML要素をコメントアウトします。
  2. HTMLフォーム要素をコメントアウトします。これを行うには、次のイメージのHTMLフォーム要素を強調表示し、[Ctrl]-[/] (Macの場合は[⌘]-[/])を押します。

    注意: 強調表示するには、マウスを使用してエディタ内でクリックしてドラッグするか、キーボードを使用して、[Shift]を押しながら矢印キーを押します。
    エディタ内で強調表示されたコード

    [Ctrl]-[/] (Macの場合は[⌘]-[/])を使用して、エディタ内のコメントを切り替えます。JavaやCSSなど、他のファイル・タイプにこのキーボード・ショートカットを適用することもできます。

  3. JSF HTMLフォーム・コンポーネントをコメント解除します。次のイメージに示すように、コンポーネントを強調表示して[Ctrl]-[/] (Macの場合は[⌘]-[/])を押します。

    注意:コードのコメントを外すには[Ctrl]-[/]を2回押すことが必要な場合があります。


    エディタ内で強調表示されたコード

    JSF HTMLフォーム・コンポーネントをコメント解除すると、<h:form><h:inputText>および<h:commandButton>タグが宣言されていないことがエディタに表示されます。

    エディタのエラー・メッセージ
  4. これらのコンポーネントを宣言するには、IDEのコード補完を使用して、タグ・ライブラリ名前空間をページの<html>タグに追加します。宣言されていないいずれかのタグにカーソルを置き、[Alt]-[Enter]を押して提案されるタグ・ライブラリを追加します。(複数のオプションがある場合は、エディタに表示されているタグを選択してから[Enter]を押してください。)JSF HTMLタグ・ライブラリ名前空間が<html>タグ(次に太字で表示)に追加され、エラー表示が消えます。

    注意:IDEでタグ・ライブラリの追加オプションが表示される場合、<html>要素を手動で変更する必要があります。

    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html">
  5. JSF式言語を使用して、UserNumberBeanuserNumberプロパティをinputTextコンポーネントにバインドします。value属性は、レンダリングされたコンポーネントの現在の値を指定するために使用できます。次の太字で表示されているコードを入力します。
    <h:form>
        <h:inputText id="userNumber" size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />

    JSF式言語では#{}構文を使用します。これらの区切り文字内で、管理対象Beanの名前と、適用するBeanプロパティを、ドット(.)で区切って指定します。これで、フォーム・データがサーバーに送られると、プロパティの設定メソッド(setUserNumber())を使用して、値が自動的にuserNumberプロパティに保存されます。また、ページがリクエストされてuserNumberの値がすでに設定されている場合、レンダリングされるinputTextコンポーネントに値が自動的に表示されます。詳細は、Java EE 7チュートリアル: 12.1.2項の式言語を使用した管理対象Beanの参照を参照してください。

  6. フォーム・ボタンをクリックして呼び出されたリクエストの宛先を指定します。フォームのHTMLバージョンでは、<form>タグのaction属性を使用してこれを実行できました。JSFの場合は、commandButtonaction属性を使用できます。また、JSF 2.xの暗黙的なナビゲーション機能により、宛先のファイルの名前を指定するのみで済みます。ファイル拡張子は不要です。

    次の太字で表示されているコードを入力します。

    <h:form>
        <h:inputText id="userNumber" size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
        <h:commandButton id="submit" value="submit" action="response" />
    </h:form>

    JSFランタイムは、responseという名前のファイルを検索します。リクエスト元のファイル(index.xhtml)で使用されているのと同じファイル拡張子であると想定し、元のファイルと同じディレクトリ内(webrootなど)でresponse.xhtmlファイルを探します。

    注意: JSF 2.xは、開発者のタスクを容易にすることを目的としています。このプロジェクトでJSF 1.2を使用している場合は、Faces構成ファイルでナビゲーション・ルールを次のように宣言する必要があります。

    <navigation-rule>
        <from-view-id>/index.xhtml</from-view-id>
    
        <navigation-case>
            <from-outcome>response</from-outcome>
            <to-view-id>/response.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>

    以降のステップ7から12は、オプションです。プロジェクトをすばやくビルドする場合は、response.xhtmlに進みます。

  7. 前出のEL式でリクエストを処理するときにsetUserNumber()メソッドが実際にコールされるかどうかをテストします。これを行うには、IDEのJavaデバッガを使用します。

    UserNumberBeanクラスに切り替えます([Ctrl]-[Tab]を押し、一覧からファイルを選択)。setUserNumber()メソッドの署名にブレークポイントを設定します。これを行うには、左マージンをクリックします。赤のバッジが表示され、メソッドのブレークポイントが設定されたことを示します。

    エディタの左マージンにあるブレークポイント
  8. IDEのメイン・ツールバーにある「プロジェクトをデバッグ」(「プロジェクトをデバッグ」ボタン)ボタンをクリックします。デバッグ・セッションが開始され、プロジェクトの開始ページがブラウザに表示されます。

    注意:

    • アプリケーションのデバッグ用のサーバー・ポートの確認を求められることがあります。
    • 「プロジェクトをデバッグ」ダイアログが表示されたら、デフォルトのサーバー側Javaオプションを選択して、「デバッグ」をクリックします。
  9. ブラウザで、フォームに数値を入力し、「送信」ボタンをクリックします。
  10. IDEに切り替え、UserNumberBeanクラスを確認します。デバッガがsetUserNumber()メソッド内で一時停止されています。
    一時停止したデバッガが表示されたエディタ
  11. デバッガの「変数」ウィンドウを開きます(「ウィンドウ」>「デバッグ」>「変数」を選択するか、[Ctrl]-[Shift]-[1]を押します)。デバッガが一時停止されている場所の変数値が表示されます。
    「変数」ウィンドウ

    前出のイメージでは、setUserNumber()署名のuserNumber変数に、値4が指定されています。(数値4がフォームに入力されたため。)「this」は、ユーザー・セッション用に作成されたUserNumberBeanオブジェクトを参照します。その下にあるuserNumberプロパティの値は、現在nullと表示されています。

  12. デバッガのツールバーで、「ステップ・イン」(ステップ・イン・ボタン)ボタンをクリックします。デバッガは、現在一時停止されている行を実行します。「変数」ウィンドウがリフレッシュされ、実行による変更が表示されます。
    「変数」ウィンドウ

    userNumberプロパティは、フォームに入力された値に設定されます。

  13. メイン・メニューから「デバッグ」→「デバッガ・セッションを終了」([Shift]-[F5]、Macでは[Shift]-[Fn]-[F5])を選択して、デバッガを停止します。

response.xhtml

  1. エディタでresponse.xhtmlページを開きます。「プロジェクト」ウィンドウで「response.xhtml」ノードをダブルクリックするか、[Alt]-[Shift]-[O]を押して「ファイルに移動」ダイアログを使用します。
  2. HTMLフォーム要素をコメントアウトします。HTML<form>の開始タグと終了タグ、およびそれらのタグ間にあるコードを強調表示し、[Ctrl]-[/] (Macの場合は[⌘]-[/])を押します。

    注意: 強調表示するには、マウスを使用してエディタ内でクリックしてドラッグするか、キーボードを使用して、[Shift]を押しながら矢印キーを押します。

  3. JSF HTMLフォーム・コンポーネントをコメント解除します。<h:form>の開始タグと終了タグ、およびそれらのタグ間にあるコードを強調表示し、[Ctrl]-[/] (Macの場合は[⌘]-[/])を押します。

    この時点では、<body>タグ間のコードは次のようになります。

    <body>
        <div id="mainContainer">
    
            <div id="left" class="subContainer greyBox">
    
                <h4>[ response here ]</h4>
    
                <!--<form action="index.xhtml">
    
                    <input type="submit" id="backButton" value="Back"/>
    
                </form>-->
    
                <h:form>
    
                    <h:commandButton id="backButton" value="Back" />
    
                </h:form>
    
            </div>
    
            <div id="right" class="subContainer">
    
                <img src="duke.png" alt="Duke waving" />
                 <!--<h:graphicImage url="/duke.png" alt="Duke waving" />-->
    
            </div>
        </div>
    </body>

    JSF HTMLフォーム・コンポーネントをコメント解除すると、エディタに<h:form><h:commandButton>タグが宣言されていないことが表示されます。

  4. これらのコンポーネントを宣言するには、IDEのコード補完を使用して、タグ・ライブラリ名前空間をページの<html>タグに追加します。

    エディタのコード補完サポートを使用して、必要なJSF名前空間をファイルに追加します。コード補完を使用してJSFまたはFaceletsタグを選択すると、必要な名前空間が自動的にドキュメントのルート要素に追加されます。詳細は、NetBeans IDEでのJSF 2.xのサポートを参照してください。

    宣言されていない任意のタグの上にカーソルを置き、[Ctrl]-[Space]を押します。コード補完による候補とドキュメント・サポートが表示されます。

    コード補完による候補とドキュメント・ポップアップ・ウィンドウ

    [Enter]を押します。(複数のオプションがある場合は、エディタに表示されているタグを選択してから[Enter]を押してください。)JSF HTMLタグ・ライブラリ名前空間が<html>タグ(次に太字で表示)に追加され、エラー表示が消えます。

    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html">
  5. フォーム・ボタンをクリックして呼び出されたリクエストの宛先を指定します。ユーザーがボタンをクリックするとindexページに戻るように、ボタンを設定します。これを行うには、commandButtonaction属性を使用します。太字で表示されているコードを入力します。
    <h:form>
    
        <h:commandButton id="backButton" value="Back" action="index" />
    
    </h:form>

    注意:action="index"」と入力すると、JSFの暗黙的なナビゲーション機能に依存することになります。ユーザーがフォーム・ボタンをクリックすると、JSFランタイムはindexという名前のファイルを検索します。リクエスト元のファイル(response.xhtml)で使用されているのと同じファイル拡張子であると想定し、元のファイルと同じディレクトリ内(webrootなど)でindex.xhtmlファイルを探します。

  6. 静的テキスト「[response here]」を、UserNumberBeanresponseプロパティの値で置き換えます。これを行うには、JSF式言語を使用します。次の太字で示したコードを入力します。
    <div id="left" class="subContainer greyBox">
    
        <h4><h:outputText value="#{UserNumberBean.response}"/></h4>
  7. プロジェクトを実行します(「プロジェクトの実行」(「プロジェクトの実行」ボタン)ボタンをクリックするか、[F6] (Macの場合は[fn]-[F6])を押します)。ブラウザに開始ページが表示されたら、数値を入力して「送信」をクリックします。次のようなレスポンス・ページが表示されます(正しい数値を推測しなかった場合)。
    ブラウザに表示されたレスポンス・ページ

    レスポンス・ページの現在の状態に、2つの間違いがあります。

    1. Html<p>タグが、レスポンス・メッセージ内に表示されています。
    2. 「戻る」ボタンが正しい位置に表示されていません。(元のバージョンと比較。)

    次の2つの手順で、これらの間違いを修正します。

  8. <h:outputText>タグのescape属性をfalseに設定します。カーソルをoutputTextvalueの間に置き、スペースを挿入してから[Ctrl]-[Space]を押して、コード補完を呼び出します。下にスクロールしてescape属性を選択し、ドキュメントを確認します。
    エディタに表示されたコード補完による候補とドキュメント

    ドキュメントで示されるように、escapeの値はデフォルトでtrueに設定されます。つまり、前出に示すように、通常はhtmlとして解析される文字がすべて文字列に含まれます。値をfalseに設定すると、htmlとして解析できるすべての文字を、そのようにレンダリングできます。

    [Enter]を押し、値として「false」と入力します。

    <h4><h:outputText escape="false" value="#{UserNumberBean.response}"/></h4>
  9. <h:form>タグのprependId属性をfalseに設定します。カーソルを<h:form>の「m」のすぐ後に置き、スペースを入力してから[Ctrl]-[Space]を押して、コード補完を呼び出します。下にスクロールしてprependId属性を選択し、ドキュメントを確認します。次に[Enter]を押し、値として「false」と入力します。
    <h:form prependId="false">

    JSFは内部IDを適用して、UIコンポーネントをトラックします。現在の例で、レンダリングされたページのソース・コードを調べると、次のように表示されます。

    <form id="j_idt5" name="j_idt5" method="post" action="/jsfDemo/faces/response.xhtml" enctype="application/x-www-form-urlencoded">
    <input type="hidden" name="j_idt5" value="j_idt5" />
        <input id="j_idt5:backButton" type="submit" name="j_idt5:backButton" value="Back" />
        <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="7464469350430442643:-8628336969383888926" autocomplete="off" />
    </form>

    フォーム要素のIDはj_idt5です。このIDは、フォームに含まれている「戻る」ボタンのIDに付加されます(太字で表示)。「戻る」ボタンは#backButtonスタイル・ルール(stylesheet.cssで定義)に依存するため、JSFのIDが付加されると、このルールが妨げられます。これを回避するには、prependIdfalseに設定します。

  10. プロジェクトを再度実行します(「プロジェクトの実行」(「プロジェクトの実行」ボタン)ボタンをクリックするか、[F6] (Macの場合は[fn]-[F6])を押します)。開始ページに数値を入力し、「送信」をクリックします。レスポンス・ページに<p>タグのないレスポンス・メッセージが表示され、「戻る」ボタンが正しい位置に配置されます。
    ブラウザに表示されたレスポンス・ページ
  11. 「戻る」ボタンをクリックします。UserNumberBeanuserNumberプロパティの現在の値はJSFinputTextコンポーネントにバインドされているため、前に入力した数値がテキスト・フィールドに表示されます。
  12. IDEの「出力」ウィンドウでサーバー・ログを確認し([Ctrl]-[4]、Macの場合は[⌘]-[4])、正しい推測値を判断します。

    なんらかの理由でサーバー・ログが表示されない場合は、「サービス」ウィンドウに切り替え([Ctrl]-[5]、Macの場合は[⌘]-[5])、「サーバー」ノードを展開します。次に、プロジェクトがデプロイされているGlassFishサーバーを右クリックし、「サーバー・ログを表示」を選択します。サーバー・ログに数値が見つけることができない場合は、プロジェクト・ノードを右クリックし、「消去してビルド」を選択して、アプリケーションを再ビルドしてみてください。

  13. 正しい数値を入力し、「送信」をクリックします。アプリケーションは、入力された数値を現在保存されている数値と比較し、適切なメッセージを表示します。
    ブラウザに表示されたレスポンス・ページ
  14. 「戻る」ボタンをもう一度クリックします。前に入力した数値はテキスト・フィールドに表示されていません。UserNumberBeangetResponse()メソッドは、正しい数値が推測されると現在のユーザー・セッションを無効にします

Faceletsテンプレートの適用

Faceletsは、JSF 2.xの標準表示テクノロジになりました。Faceletsは、すべてのJSF UIコンポーネントをサポートする軽量テンプレート作成フレームワークで、アプリケーション・ビュー用のJSFコンポーネント・ツリーをビルドおよびレンダリングするのに使用されます。また、ユーザーがスタック・トレース、コンポーネント・ツリー、およびスコープ指定された変数を確認できるようにすることで、ELエラー発生時の開発サポートを提供します。

チュートリアルでこれまでに操作してきたindex.xhtmlおよびresponse.xhtmlファイルは、Faceletsページです。Faceletsページでは.xhtml拡張子が使用されます。また、JSF 2.xプロジェクトで作業しているため(JSF 2.xライブラリにはFacelets JARファイルが含まれる)、ビューではJSFコンポーネント・ツリーを適切にレンダリングできました。

この項は、Faceletsのテンプレート作成に慣れることを目的としています。多くのビューを含むプロジェクトの場合、複数のビューの構造および外観を定義するテンプレート・ファイルを適用すると便利なことがよくあります。アプリケーションでは、リクエストをサービスするときに、動的に用意されたコンテンツをテンプレート・ファイルに挿入し、結果をクライアントに送り返します。このプロジェクトに含まれているビューは2つ(開始ページとレスポンス・ページ)のみですが、これらのビューには重複するコンテンツが多数含まれています。重複するコンテンツをFaceletsテンプレートにまとめて、テンプレート・クライアント・ファイルを作成し、開始ページとレスポンス・ページに固有のコンテンツを処理することができます。

IDEには、Faceletsテンプレートを作成するためのFaceletsテンプレート・ウィザードと、テンプレートに依存するファイルを作成するためのFaceletsテンプレート・クライアント・ウィザードが用意されています。この項では、これらのウィザードを使用します。

注意: IDEには、プロジェクト用に個々のFaceletsページを作成するための、JSFページ・ウィザードも用意されています。詳細は、NetBeans IDEでのJSF 2.xのサポートを参照してください。

Faceletsテンプレート・ファイルの作成

  1. Faceletsテンプレート・ファイルを作成します。[Ctrl]-[N] (Macの場合は[⌘]-[N])を押して、ファイル・ウィザードを開きます。「JavaServer Faces」カテゴリを選択し、「Faceletsテンプレート」を選択します。「次」をクリックします。
  2. ファイル名として「template」と入力します。
  3. 8つのレイアウト・スタイルから任意のスタイルを選択し、「終了」をクリックします。(既存のスタイル・シートを使用するので、どのレイアウト・スタイルを選択してもかまいません。)
    Faceletsテンプレート・ウィザードに提示されたレイアウト・スタイル
    ウィザードで、選択に基づいてtemplate.xhtmlファイルおよび付属するスタイル・シートが生成され、プロジェクトのwebroot内の「resources」>「css」フォルダに置かれます。

    ウィザードが完了すると、テンプレート・ファイルがエディタに開かれます。ブラウザでこのテンプレートを表示するには、エディタ内を右クリックし、「表示」を選択します。

  4. テンプレート・ファイルのマークアップを確認します。次の点を確認します。
    • faceletsタグ・ライブラリがページの<html>タグ内で宣言されています。タグ・ライブラリに接頭辞uiがあります。
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:h="http://java.sun.com/jsf/html">
    • Faceletsページで、htmlの<head>および<body>タグではなく、<h:head>および<h:body>タグが使用されています。Faceletsは、これらのタグを使用することによって、ページ全体にわたるコンポーネント・ツリーを構築できます。
    • ページは、ウィザードの完了時に作成されたスタイル・シートを参照します。
      <h:head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          <link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
          <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
          <title>Facelets Template</title>
      </h:head>
    • <ui:insert>タグは、選択したレイアウト・スタイルに関連付けられているすべての区画のページ本体で使用されます。それぞれの<ui:insert>タグには、区画を識別するname属性があります。例:
      <div id="top">
          <ui:insert name="top">Top</ui:insert>
      </div>
  5. 開始ページとレスポンス・ページを再度確認します。2つのページ間で異なるコンテンツは、グレーの四角形の中にあるタイトルとテキストのみです。そのため、テンプレートで残りのすべてのコンテンツを提供できます。
  6. テンプレート・ファイルのすべてのコンテンツを、次のコンテンツに置き換えます。
    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html">
    
        <h:head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <link href="css/stylesheet.css" rel="stylesheet" type="text/css" />
    
            <title><ui:insert name="title">Facelets Template</ui:insert></title>
        </h:head>
    
        <h:body>
    
            <div id="left">
                <ui:insert name="box">Box Content Here</ui:insert>
            </div>
    
        </h:body>
    
    </html>
    このコードによって、次の変更が実装されます。
    • プロジェクトのstylesheet.cssファイルによって、ウィザードで作成されたテンプレート・スタイル・シート参照が置き換えられます。
    • <ui:insert>タグ(およびそれらに含まれる<div>タグ)が、boxという名前のものを除き、すべて除去されます。
    • ページ・タイトルを囲んで<ui:insert>タグ・ペアが配置され、titleという名前が付けられています。
  7. 該当するコードを、index.xhtmlまたはresponse.xhtmlファイルからテンプレートにコピーします。次に太字で示されているコンテンツを、テンプレート・ファイルの<h:body>タグに追加します。
    <h:body>
        <div id="mainContainer">
            <div id="left" class="subContainer greyBox">
                <ui:insert name="box">Box Content Here</ui:insert>
            </div>
            <div id="right" class="subContainer">
                <img src="duke.png" alt="Duke waving" />
            </div>
        </div>
    </h:body>
  8. プロジェクトを実行します。ブラウザで開始ページが開いたら、URLを次のように変更します。
    http://localhost:8080/jsfDemo/faces/template.xhtml
    テンプレート・ファイルが次のように表示されます。
    ブラウザに表示されたFaceletsテンプレート

これで、プロジェクトには、すべてのビューの外観と構造を定義するテンプレート・ファイルが作成されました。ここで、テンプレートを呼び出すクライアント・ファイルを作成できます。

テンプレート・クライアント・ファイルの作成

開始ページおよびレスポンス・ページ用のテンプレート・クライアント・ファイルを作成します。開始ページのテンプレート・クライアント・ファイルには、greeting.xhtmlという名前を付けます。レスポンス・ページのファイルには、response.xhtmlという名前を付けます。

greeting.xhtml

  1. [Ctrl]-[N] (Macの場合は[⌘]-[N])を押して、新規ファイル・ウィザードを開きます。「JavaServer Faces」カテゴリを選択し、「Faceletsテンプレート・クライアント」を選択します。「次」をクリックします。
  2. ファイル名として「greeting」と入力します。
  3. 「テンプレート」フィールドの横にある「参照」ボタンをクリックし、表示されたダイアログを使用して、前の項で作成したtemplate.xhtmlファイルに移動します。
    Faceletsテンプレート・クライアント・ウィザード
  4. 「終了」をクリックします。新しいテンプレート・クライアント・ファイルgreeting.xhtmlが生成され、エディタに表示されます。
  5. マークアップを確認します。太字で強調表示されているコンテンツを確認してください。
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets">
    
        <body>
    
            <ui:composition template="./template.xhtml">
    
                <ui:define name="title">
                    title
                </ui:define>
    
                <ui:define name="box">
                    box
                </ui:define>
    
            </ui:composition>
    
        </body>
    </html>
    テンプレート・クライアント・ファイルは、<ui:composition>タグのtemplate属性を使用して、テンプレートを参照します。テンプレートにはtitleおよびbox<ui:insert>タグが含まれているため、このテンプレート・クライアントには、これらの2つの名前の<ui:define>タグが含まれます。<ui:define>タグの間で指定するコンテンツは、テンプレートの対応する名前の<ui:insert>タグの間に挿入されるコンテンツです。
  6. ファイルのタイトルとして「greeting」を指定します。次に太字で示す変更を加えます。
    <ui:define name="title">
        Greeting
    </ui:define>
  7. index.xhtmlファイルに切り替え([Ctrl]-[Tab])、表示されるページで、通常はグレーの四角形内に表示されるコンテンツをコピーします。greeting.xhtmlに切り替え、テンプレート・クライアント・ファイルに貼り付けます。変更場所は太字で示されています。
    <ui:define name="box">
        <h4>Hi, my name is Duke!</h4>
    
        <h5>I'm thinking of a number
    
            <br/>
            between
            <span class="highlight">0</span> and
            <span class="highlight">10</span>.</h5>
    
        <h5>Can you guess it?</h5>
    
        <h:form>
            <h:inputText size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
            <h:commandButton id="submit" value="submit" action="response" />
        </h:form>
    </ui:define>
  8. ファイルのJSF HTMLタグ・ライブラリを宣言します。エラーのフラグが付いているタグ(「h」接頭辞を使用するタグ)にカーソルを置き、[Ctrl]-[Space]を押します。コード補完による候補の一覧から、タグを選択します。タグ・ライブラリ名前空間がファイルの<html>タグ(太字で表示)に追加され、エラー表示が消えます。
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html">

    <h:form>の「m」の後にカーソルを置き、[Ctrl]-[Space]を押すと、名前空間が自動的にファイルに追加されます。[Ctrl]-[Space]を押したときに使用可能な論理オプションが1つのみの場合は、それがすぐにファイルに適用されます。タグ上でコード補完を呼び出すときに、JSFタグ・ライブラリが自動的に宣言されます。

response.xhtml

プロジェクトにはresponse.xhtmlという名前のファイルがすでに含まれており、テンプレート・クライアント・ファイルの内容もわかっているので、既存のresponse.xhtmlを変更して、テンプレート・クライアント・ファイルにします。(このチュートリアルでは、提供されているコードをコピーして貼り付けます。)

  1. エディタでresponse.xhtmlを開きます。(すでに開かれている場合は、[Ctrl]-[Tab]を押して選択します。)ファイル全体のコンテンツを、次のコードで置き換えます。
    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html">
    
        <body>
    
            <ui:composition template="./template.xhtml">
    
                <ui:define name="title">
                    Response
                </ui:define>
    
                <ui:define name="box">
                    <h4><h:outputText escape="false" value="#{UserNumberBean.response}"/></h4>
    
                    <h:form prependId="false">
    
                        <h:commandButton id="backButton" value="Back" action="greeting" />
    
                    </h:form>
                </ui:define>
    
            </ui:composition>
    
        </body>
    </html>
    titleおよびbox<ui:define>タグ間で指定されているコンテンツを除き、ファイルはgreeting.xhtmlと同じになります。
  2. プロジェクトのweb.xmlデプロイメント・ディスクリプタで、アプリケーションを実行したときにgreeting.xhtmlページが開かれるように、開始ファイルのエントリを変更します。

    「プロジェクト」ウィンドウで「構成ファイル」>「web.xml」をダブルクリックして、エディタで開きます。「ページ」タブで「開始ファイル」フィールドを「faces/greeting.xhtml」に変更します。
    デプロイメント・ディスクリプタ・インタフェース
  3. プロジェクトを実行して、ブラウザでどのように表示されるかを確認します。[F6] (Macの場合は[fn]-[F6])を押すか、メイン・ツールバーの「プロジェクトの実行」(「プロジェクトの実行」ボタン)ボタンをクリックします。プロジェクトがGlassFishサーバーにデプロイされ、ブラウザで開かれます。

Faceletsテンプレートおよびテンプレート・クライアント・ファイルを使用して、アプリケーションは以前とまったく同じように動作します。アプリケーションの開始ページとレスポンス・ページで重複しているコードを取り除くことによって、アプリケーションのサイズを小さくするとともに、後でページが追加されたときに重複したコードを記述することがなくなりました。これにより、大規模なプロジェクトで作業するときに、開発作業が効率化され、管理が容易になります。


関連項目

JSF 2.xの詳細は、次のリソースを参照してください。

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo