この章では、図書検索プログラムを発展させた、図8.1[詳細なデータを表示]のようなサンプルについて考えてみましょう。
図書検索アプリケーションの検索結果表示画面で、本のタイトルをクリックすると、詳細なデータが出るようにします。
「リンクをクリック」することによって、詳細表示画面に遷移します。そのためには、「どの本のデータがクリックされたか」を知る必要があります。具体的には、h:dataTableでどのJavaBeansのデータがクリックされたかをチェックするのです。
では、検索結果表示画面の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行分に対応します。
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のソースを見てみましょう。
<%@ 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}" />