Powered by SmartDoc

Action Method の実装

Action Method の実行

この章では、図7.1[名前と現在の時刻を表示する]のようなサンプルについて考えてみましょう。

名前と現在の時刻を表示する

まず、画面1で名前を入力します。画面1のボタンを押すと、画面2に遷移します。画面2では、画面1で入力された名前と、現在の時刻を表示しています。

このサンプルでは、ボタンが押されたときに、「現在の時刻を取得する」という「ビジネスロジック」が実行されています。JSFでは、こうしたビジネスロジックのことを「Action Method」と言います。Action Methodは、Managed Beanに記述します。

Action Method と Method Binding

Managed Bean の実装

では、このサンプルのManaged Beanを見てみましょう。

ParameterBean.java
import java.util.Date;
import java.text.DateFormat;

public class ParameterBean {

    private String word = "";

    public void setWord(String word) {
        this.word = word;
    }

    public String getWord() {
        return word;
    }

    public String currentTime() {
        Date d = new Date();
        DateFormat df = DateFormat.getDateTimeInstance();

        StringBuffer sb = new StringBuffer();
        sb.append("こんにちは、");
        sb.append(word);
        sb.append("さん。\n");
        sb.append("いまは");
        sb.append(df.format(d));
        sb.append("です。");

        word = new String(sb);

        return "success";
    }
}

このManaged Beanでは、currentTimeというメソッドがAction Methodになります。

このcurrentTimeメソッドでは、現在の日時を取得して、入力フィールドのパラメータと組み合わせています。

そして、返値として"success"という文字列を返しているのがポイントです。

JSP と Method Binding

では、画面1に対応するJSPを見てみましょう。

page1.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>
<head>
<link href="style.css" type="text/css" rel="stylesheet" />
<title>JSF: ビジネスロジックのテスト</title>
</head>
<body>

<h1>JSF: ビジネスロジックのテスト</h1>

<f:view>
    <h:form id="searchForm">
        <h:inputText id="word" value="#{ParameterBean.word}" />
        <h:commandButton id="button1"
             action="#{ParameterBean.currentTime}" value="Go!" />
    </h:form>
</f:view>

</body>
</html>

h:commandButton要素のaction属性に注目してください。

        <h:commandButton id="button1"
             action="#{ParameterBean.currentTime}" value="Go!" />

action属性の値は、#{ParameterBean.currentTime}という表記になっています。

これを、前章のh:commandButton要素のaction属性と比較してみましょう。

(前章の action 属性)
        <h:commandButton id="button1"
             action="success" value="Go!" />

(本章の action 属性)
        <h:commandButton id="button1"
             action="#{ParameterBean.currentTime}" value="Go!" />

前章では、"success"となっているのに対し、本章では、前章で出てきたValue Binding式のようなスタイルになっています。

では、#{ParameterBean.currentTime}という表記について解説しましょう。

ここでは、画面1のボタンが押されると、ParameterBeanのcurrentTimeメソッドが実行されるのです。こうしたしくみのことを"Method Binding"と言います。そして、#{……}という書式を"Method Binding式"と言います。

Method Binding 式

Method Binding式は、次のようなスタイルになります。

#{ Beanの名前 . Action Method名 }

"Beanの名前"は、先のmanaged-bean-name要素の内容部分となります。

"Action Method名"は、ボタンが押されたときに実行されるAction Method名になります。

Action Method のルール

Action Methodには、次の3つのルールがあります。

currentTimeメソッドが、この3つのルールに適合していることを確認してください。

Action Method の返値と outcome

いま説明したように、Action Methodの返値がoutcomeとなります。このoutcomeが、h:commandButton要素のaction属性の値となるのです。この値と、faces-config.xmlの設定情報により遷移先が決まります。

次のようなh:commandButtonタグの記述が

        <h:commandButton id="button1"
             action="#{ParameterBean.currentTime}" value="Go!" />

currentTimeというAction Methodの実行によって、次のように変化するというイメージです。

        <h:commandButton id="button1"
             action="success" value="Go!" />

図書検索プログラムの作成 (1)

プログラムの概要

では、ここでもう一つサンプルプログラムを作ってみましょう。題材は「図書検索プログラム」です。

図7.2[検索語入力画面]で検索語を入力すると、その検索語を含む本のデータのリストを出力します。図書データはデータベースに格納されています。

検索語入力画面

入力フィールドに検索語を入れ、ボタンを押すと、Action Methodが呼ばれます。Action Methodで検索語に基づく検索を行います。そして図7.3[検索結果出力画面]に遷移して、検索結果を出力するのです。

検索結果出力画面

検索語入力画面のJSP

search.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>
<head>
<link href="style.css" type="text/css" rel="stylesheet" />
<title>図書検索</title>
</head>
<body>

<h1>図書検索</h1>

<hr />

<f:view>
    <h:form id="searchForm">
        <h:inputText id="searchWord" value="#{BookSearcher.word}" />
        <h:commandButton id="submit"
             action="#{BookSearcher.searchBooks}" value="Go!" />
    </h:form>
</f:view>

</body>
</html>

h:input要素でValue Binding式、h:commandButton要素でMethod Binding式が使われています。

Managed Bean の実装

次に、Managed Beanです。

BookSearcher.java
import java.util.List;
import java.util.ArrayList;
import java.sql.*;
import javax.sql.*;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;

public class BookSearcher {

    private String word = "";
    private String id   = "";
    private List list = null;
    private BookData book = null;

    public void setWord(String word) {
        this.word = word;
    }

    public String getWord() {
        return word;
    }

    public List getBookList() {
        return list;
    }

    public BookData getBookData() {
        return book;
    }

    public String searchBooks() {
        searchBooks(word);
        return "success";
    }

    private void searchBooks(String word) {
        list = new ArrayList();
        try {
            Class.forName("org.hsqldb.jdbcDriver");
            String url = "jdbc:hsqldb:hsql://localhost";
            Connection con = DriverManager.getConnection(url, "sa", "");

            String selectStatement =
                "select * " +
                "from books where ndc           like ? " +
                              "or tyosya_hyouji like ? " +
                              "or id            like ? " +
                              "or title         like ? " +
                              "or author        like ? " +
                              "or publisher     like ? ";
            PreparedStatement prepStmt =
                con.prepareStatement(selectStatement);
            prepStmt.setString(1, appendPercent(word));
            prepStmt.setString(2, appendPercent(word));
            prepStmt.setString(3, appendPercent(word));
            prepStmt.setString(4, appendPercent(word));
            prepStmt.setString(5, appendPercent(word));
            prepStmt.setString(6, appendPercent(word));

            ResultSet rs = prepStmt.executeQuery();
            while (rs.next()) {
                BookData book = new BookData();
                book.setNdc(rs.getString("ndc"));
                book.setTyosya_hyouji(rs.getString("tyosya_hyouji"));
                book.setId(rs.getString("id"));
                book.setTitle(rs.getString("title"));
                book.setAuthor(rs.getString("author"));
                book.setPublisher(rs.getString("publisher"));
                list.add(book);
            }
            prepStmt.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private String appendPercent(String from) {
        StringBuffer to = new StringBuffer();
        to.append("%");
        to.append(from);
        to.append("%");

        return new String(to);
    }

}

setWord, getWordというメソッドの存在から、wordプロパティがあることがわかります。また、bookList, bookDataプロパティもあります。

そして、searchBooksというAction Methodがあります。Action Methodのルールに則っていることがわかります。このメソッドでは、(別の)searchBooksメソッドで、データベースの検索処理を行っています。

public String searchBooks() {
    searchBooks(word);
    return "success";
}

private void searchBooks(String word) {
    // データベースの検索処理
}

Model

次に、ModelとなるBookDataというJavaBeansです。

BookData.java
import java.io.Serializable;

public class BookData implements Serializable {

    private String ndc           = "";
    private String tyosya_hyouji = "";
    private String id            = "";
    private String title         = "";
    private String author        = "";
    private String publisher     = "";

    public String getNdc() {
        return ndc;
    }

    public void setNdc(String ndc) {
        this.ndc = ndc;
    }

    public String getTyosya_hyouji() {
        return tyosya_hyouji;
    }

    public void setTyosya_hyouji(String tyosya_hyouji) {
        this.tyosya_hyouji = tyosya_hyouji;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

}

ndc, tyosya_hyouji, titleなどのプロパティがあることがわかります。

データベースの検索結果には、複数の図書データが含まれます。1冊の図書データは、1つのBookDataに格納されます。そしてjava.util.Listを使って、複数のBookDataをまとめておきます。

次のような処理になります。

List list = new ArrayList();

BookData book = new BookData();
book.setId(rs.getString("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));

list.add(book);

検索結果出力画面のJSP

検索結果を出力するJSPです。

list.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib uri="http://java.sun.com/jsf/html"  prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core"  prefix="f" %>

<html>
<head>
<title>検索結果</title>
</head>
<body>

<h1>検索結果</h1>

<f:view>
<h:form id="listForm">
<h:dataTable id="table" border="1"
              value="#{BookSearcher.bookList}" var="book">
    <h:column>
        <f:facet name="header">
            <h:outputText  value="タイトル"/>
        </f:facet>
        <h:outputText id="bookTitle" value="#{book.title}"/>
    </h:column>
    <h:column>
        <f:facet name="header">
            <h:outputText  value="著者"/>
        </f:facet>
        <h:outputText id="bookAuthor" value="#{book.author}"/>
    </h:column>
</h:dataTable>
</h:form>
</f:view>

</body>
</html>

主に、dataTableというタグを使って検索結果を表示しています。

h:dataTable タグ

h:dataTableタグは、コレクション(List,配列など)のデータを表にして表示するUIコンポーネントです。

ほかのUIコンポーネントと同じく、id属性があります。border属性では、表の罫線の太さを指定しています。

value属性で、表示するコレクション型のプロパティを指定します。このとき、Value Binding式を使います。var属性は、コレクション中の1つの要素を表す変数名です。

この例では、value属性はList型であるbookListプロパティを指定しています。このbookListには、複数のBookDataが格納されています。従って、var属性で指定されたbookという変数名は、BookData Beanを指していることになります。

<h:dataTable id="table" border="1"
              value="#{BookSearcher.bookList}" var="book">
</h:dataTable>

h:column タグとデータの出力

h:dataTableタグでは、複数のh:columnタグが含まれています。このタグは、図7.4[h:column タグ]のように、h:dataTable要素の1列分のデータを表すUIコンポーネントです。

h:column タグ
<h:dataTable id="table" border="1"
              value="#{BookSearcher.bookList}" var="book">
    <h:column>
        <f:facet name="header">
            <h:outputText  value="タイトル"/>
        </f:facet>
        <h:outputText id="bookTitle" value="#{book.title}"/>
    </h:column>
    ......

h:column要素には、f:facet要素とh:outputText要素が含まれています。

このうち、f:facet要素は、表の1列のヘッダやフッタを表すUIコンポーネントです。

name属性に"header"を指定するとヘッダになります。"footer"だとフッタです。

        <f:facet name="header">
            <h:outputText  value="タイトル"/>
        </f:facet>

そして、h:outputTextタグです。この列では、bookという変数(BookData Beanのこと)のtitleプロパティの値を出力しています。

        <h:outputText id="bookTitle" value="#{book.title}"/>

h:dataTable の働き

では、h:dataTableタグの働きについて整理してみましょう。

表示される表の1行分が、h:dataTableのvar属性の値に対応しています。つまり、コレクション中の1つのJavaBeansが、表の1行分となるのです。この例では、List中の1つのBookDataが、表の1行分となります。

BookData Beanのどのプロパティを出力するかは、column要素によって決まります。1つのcolumn要素で、1つのプロパティを出力するのです。