今回は、JSF(JavaServer Faces)コンポーネント・スイートの「PrimeFaces」を用いて、UIコンポーネントとサーバ側のManagedBeanオブジェクトを連携させる例を紹介する。具体的には、フォームから入力されたメッセージをサーバ側のオブジェクトに記録し、その内容をテーブルでページに表示するというアプリケーションを作ってみる。

ManagedBeanの作成

まず、送られたメッセージを保持するためのクラスをMessageクラスとして、次のように定義する。このクラスはプロパティとしてString型の"name"と"value"を持つ。

package jp.co.mycom.toolde.primefaces;


import java.io.Serializable;


public class Message implements Serializable {
  private String name = null;
  private String value = null;

  public String getName() {
    return name;
  }
  public String getValue() {
    return value;
  }


  public void setName(String name) {
    this.name = name;
  }
  public void setValue(String value) {
    this.value = value;
  }
}

ManagedBeanは、フォームから入力されたメッセージを受け取って記憶し、その一覧をテーブルに反映させるというものである。今回はAddMessageBeanクラスとして、次のように実装した。

package jp.co.mycom.toolde.primefaces;


import java.util.List;
import java.util.ArrayList;


public class AddMessageBean {
  private Message message = new Message();
  private List<Message> messages = new ArrayList<Message>();


  public void addMessage() {
    this.messages.add(this.message);
    this.message = new Message();  // フォームのリセット
  }

  public Message getMessage() {
    return this.message;
  }
  public void setMessage(Message message) {
    this.message = message;
  }


  public List<Message> getMessages() {
    return this.messages;
  }
}

AddMessageBeanクラスは"message"と"messages"という2つのプロパティを持つ。messageは単体のMessageオブジェクトであり、フォームから入力された最新のメッセージと名前を保持する。一方でmessagesはMessageを格納するListオブジェクトであり、それまでに入力されたメッセージ/名前を記憶するためのものである。

このクラスにはもうひとつ、addMessage()メソッドが定義してある。これはユーザがメッセージの送信ボタンを押したときに呼び出され、そのときにmessageプロパティが保持しているMessageオブジェクトをmessagesに追加するという役割のメソッドである。追加後は、フォームの中身を空にするために、messageプロパティに新しいMessageオブジェクトを格納する。

このAddMessageBeanクラスをManagedBeanとして利用可能にするために、faces-config.xmlには次のような設定を追加する。

<managed-bean>
  <managed-bean-name>addMessageBean</managed-bean-name>
  <managed-bean-class>jp.co.mycom.toolde.primefaces.AddMessageBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

この設定により、HTML側では"addMessageBean"という名称でサーバ側のAddMessageBeanオブジェクトにアクセスできる。スコープは"session"にしたので、Webブラウザとアプリケーションの間にセッションが確立している間は記憶されたデータが有効になる。もしもっと長期間データを保持しておきたい場合には、addMessage()の部分にMessageオブジェクトの永続化の機構を組み込めばいいということになる。

PrimeFacesのコンポーネントとの連携

続いてWebブラウザに表示するUIを作成する。必要なコンポーネントはメッセージと名前を入力するテキストフィールドと、送信用のボタン、そして登録されたメッセージを一覧表示するテーブルである。テキストフィールドは、PrimeFacesではというタグで利用できる。例えばメッセージを入力するためのテキストフィールドは次のように記述できる。

<p:inputText id="name" value="#{addMessageBean.message.value}" required="true" label="Name"/>

この例の場合、value属性の値(すなわち入力されたテキスト)を、サーバ側のAddMessageBeanオブジェクトのmessageプロパティのvalueの値に関連付けている。

ボタンはタグで作成する。action属性に#{addMessageBean.addMessage}を指定することで、AddMessageBeanのaddMessage()メソッドを実行する。またupdate属性を付加することで、指定されたIDのコンポーネントの表示を更新するようになる。

<p:commandButton value="送信" action="#{addMessageBean.addMessage}" update="@form"/>

は、JSFのとよく似ているが、最大の違いはPrimeFacesのスキンが適用されるという点である。また、前述のupdateのようにいくつかの独自の属性が利用できるというメリットもある。

テーブルはで作成できる。各カラムの内容はとよく似ている。

<p:dataTable value="#{addMessageBean.messages}" var="message">
  <p:column>
    <f:facet name="header">
      <h:outputText value="名前" />
    </f:facet>
    <h:outputText value="#{message.name}" />
  </p:column>
  <p:column>
    <f:facet name="header">
      <h:outputText value="メッセージ" />
    </f:facet>
    <h:outputText value="#{message.value}" />
  </p:column>
</p:dataTable>

以上をまとめると、XHTMLによるページは次のように記述できる。

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.prime.com.tr/ui">

  <h:head>
    <title>PrimeFacesのサンプル</title>
  </h:head>

  <h:body>
    <h1>メッセージボード</h1>

    <h:form>

      <h:panelGrid columns="2">
        <h:outputLabel value="名前 :" for="name" />
        <p:inputText id="name" value="#{addMessageBean.message.name}" required="true" label="Name"/>

        <h:outputLabel value="メッセージ :" for="message" />
        <p:inputText id="message" value="#{addMessageBean.message.value}" required="true" label="Message"/>
      </h:panelGrid>

      <p:commandButton value="送信" action="#{addMessageBean.addMessage}" update="@form"/>


      <p:dataTable value="#{addMessageBean.messages}" var="message">
        <p:column>
            <f:facet name="header">
                <h:outputText value="名前" />
            </f:facet>
            <h:outputText value="#{message.name}" />
        </p:column>
        <p:column>
            <f:facet name="header">
                <h:outputText value="メッセージ" />
            </f:facet>
            <h:outputText value="#{message.value}" />
        </p:column>
      </p:dataTable>


    </h:form>


  </h:body>
</html>

完成したら、アプリケーションサーバに配備してWebブラウザからアクセスしてみよう。最初はのように表示され、名前とメッセージを入力していくとのようにテーブルに入力した名前/メッセージが反映されていく。

名前とメッセージの入力フィールドが表示される。テーブルの中身は最初は空になっている

名前/メッセージを入力すると、それがテーブルに反映されていく

テーブルをソート可能にする

テーブルのデータをカラムごとにソートできるようにするには、対象とするカラムの

<p:dataTable value="#{addMessageBean.messages}" var="message">
  <p:column sortBy="#{message.name}">
    <f:facet name="header">
      <h:outputText value="名前" />
    </f:facet>
    <h:outputText value="#{message.name}" />
  </p:column>
  <p:column sortBy="#{message.value}">
    <f:facet name="header">
      <h:outputText value="メッセージ" />
    </f:facet>
    <h:outputText value="#{message.value}" />
  </p:column>
</p:dataTable>

Webブラウザからアクセスすると、のようにカラム名の部分をクリックすると昇順/降順にソートされるようになっていることが確認できる。

カラム名をクリックするとソートされる

テーブルにフィルタ機能を付ける

テーブルに対してフィルタの機能を付け加えることも簡単にできる。ソートの場合と同様に、

<p:dataTable value="#{addMessageBean.messages}" var="message">
  <p:column sortBy="#{message.name}" filterBy="#{message.name}">
    <f:facet name="header">
      <h:outputText value="名前" />
    </f:facet>
    <h:outputText value="#{message.name}" />
  </p:column>
  <p:column sortBy="#{message.value}" filterBy="#{message.value}" filterMatchMode="startsWith">
    <f:facet name="header">
      <h:outputText value="メッセージ" />
    </f:facet>
    <h:outputText value="#{message.value}" />
  </p:column>
</p:dataTable>

Webページ上の表示では、のようにカラム名にフィルタリングのための入力フィールドが表示される。ここに文字列を入力すると、のように条件にマッチした行だけが表示されるようになる。

カラム名にフィルタリングのための入力フィールドが表示される

文字を入力すると、条件にマッチした行だけが表示される

今回は一部のコンポーネントの使い方と、ManagedBeanとの連携のさせ方を紹介したが、PrimeFacesの最大の強みはそのコンポーネントの数である。どのようなコンポーネントが用意されているかは、公式サイトのショーケースにまとめられている。