この章では、図書検索プログラムを発展させた、図11.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}" />