Powered by SmartDoc

FacesContext クラスの利用

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

プログラムの概要

この章では、図書検索プログラムを発展させた、図8.1[詳細なデータを表示]のようなサンプルについて考えてみましょう。

詳細なデータを表示

図書検索アプリケーションの検索結果表示画面で、本のタイトルをクリックすると、詳細なデータが出るようにします。

どのような機能を追加するのか

「リンクをクリック」することによって、詳細表示画面に遷移します。そのためには、「どの本のデータがクリックされたか」を知る必要があります。具体的には、h:dataTableでどのJavaBeansのデータがクリックされたかをチェックするのです。

h:commandLink タグ

では、検索結果表示画面の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:commandLink id="detail"
                   action="#{BookSearcher.searchBookDetail}">
            <h:outputText id="bookTitle" value="#{book.title}"/>
        </h:commandLink> 
    </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>

本のタイトルを表示するh:outputTextタグを、h:commandLinkタグで囲っています。ここが前章との違いです。

このh:commandLinkタグは、ハイパーリンクを実現するためのUIコンポーネントです。id属性があります。また、action属性では、Action Methodを指定します。

h:outputText要素で指定された文字列をクリックすると、Action Methodのoutcomeとfaces-config.xmlの設定によって画面が遷移します。

        <h:commandLink id="detail"
                   action="#{BookSearcher.searchBookDetail}">
            <h:outputText id="bookTitle" value="#{book.title}"/>
        </h:commandLink> 

何が問題になるのか?

クリックされたらそのデータの詳細表示に遷移します。ではどうやって「どのデータがクリックされたか」知るのでしょうか?どのデータがクリックされたか、Action Methodが知っておく必要があります。

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

var属性は、コレクション中の1つの要素を表す変数名となります。List中の1つのBookDataが、表の1行分に対応します。

Action Method の実装

BookSearcher.java
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.sql.*;
import javax.sql.*;
import javax.faces.context.FacesContext;
import javax.faces.context.ExternalContext;
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";
    }

    public String searchBookDetail() {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext exContext = context.getExternalContext();
        Map map = exContext.getRequestMap();
        book = (BookData)map.get("book");
        return "detail";
    }

    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);
    }

}

searchBookDetailメソッドがAction Methodになります。

        FacesContext context = FacesContext.getCurrentInstance();

FacesContextは、JSFアプリケーションの現在の状態を保持しているオブジェクトです。JSFの状態を取得するための出発点となるオブジェクトになります。

        ExternalContext exContext = context.getExternalContext();

ExternalContextは、ServletやPortletからJSFを利用することを(特に)意識しているクラスです。requestやsessionスコープの中で管理されているオブジェクトを取り出すことができます。

        Map map = exContext.getRequestMap();
        book = (BookData)map.get("book");

requestスコープで管理されている情報をMapで取得します。Mapから、(ハイパーリンクを)クリックした行のbook変数に対応付けられているBookDataオブジェクトが取得できます。このオブジェクト(Bean)のデータを詳細画面で表示するのです。

詳細表示のJSP

では、詳細表示を行うJSPのソースを見てみましょう。

detail.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>
<ul>
<li><h:outputText value="#{BookSearcher.bookData.ndc}" />
<li><h:outputText value="#{BookSearcher.bookData.tyosya_hyouji}" />
<li><h:outputText value="#{BookSearcher.bookData.id}" />
<li><h:outputText value="#{BookSearcher.bookData.title}" />
<li><h:outputText value="#{BookSearcher.bookData.author}" />
<li><h:outputText value="#{BookSearcher.bookData.publisher}" />
</ul>
</f:view>

</body>
</html>

次の部分では、BookSearcher BeanのbookDataプロパティのidプロパティを表示しています。

<li><h:outputText value="#{BookSearcher.bookData.id}" />