JSFとUnified EL

続いて、JSP 2.1から導入された式言語であるUnified Expression Languageを試してみよう。JSP 2.0の式言語では、リスト17でも使っているように${list}や${item.id}というような式で変数の値を参照することができた。

リスト17 JSP 2.0の式言語を使ったitemlist.jsp

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP 2.1のテスト</title>
    </head>
    <body>
 
        <h1>Resource Injection</h1>
    
        <%@page import="java.sql.*,javax.sql.*,javax.naming.*"%>
        <%@page import="javax.annotation.Resource"%>
        <%@page import="java.util.*"%>
 
        <jsp:declaration>
            @Resource(name="sampledatabase") 
            javax.sql.DataSource datasource;
        </jsp:declaration>
 
        <jsp:scriptlet>
            List list = new ArrayList();
            Connection con = datasource.getConnection();
            Statement stat = con.createStatement();
            String sql = "select * from item";
            ResultSet resultSet = stat.executeQuery(sql);
            while(resultSet.next()) {
                Map map = new HashMap();
                map.put("id", resultSet.getInt("id"));
                map.put("name", resultSet.getString("name"));
                list.add(map);
            }
            con.close();
            request.setAttribute("list",list);
        </jsp:scriptlet>
 
        <table border=\"1\">
            <thead><tr><th>ID</th><th>Item</th></tr></thead>
            <tbody>
                <c:forEach var="item" items="${list}">
                    <tr><td>${item.id}</td><td>${item.name}</td></tr>
                </c:forEach>
            </tbody>
        </table>
 
    </body>
</html>

一方でJSFでは#{item.id}という式を使用する。この違いにより、JSFとJSPを併用している場合に異なる式が混在するという事態になる。

そこで2つの式言語を統一し、同じ表記が使用できるようにUnified ELが導入された。Unified ELでは${}形式と#{}形式の両方の式を使用することができる。両者の大きな違いは、${}が即時評価であるのに対して#{}は遅延評価である点だ。${}式はJSPページが読み込まれた際に評価されるが、#{}式はJSPのライフサイクルの外で動作することになる。

さて、このUnified ELを使用したJSPページの例をリスト18に示す。これはJSFを使ったWebアプリケーションのためのページで、JSFとJSPのタグが混在しており、JSTLのc:forEachタグの中で#{}式を利用している。

リスト18 Unified ELの使ったitemlistJSF.jsp

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
 
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP 2.1のテスト</title>
    </head>
    <body>
        <f:view>
            <h1><h:outputText value="Unified EL" /></h1>
            <h:form id="searchForm">
                <h:commandButton id="viewItems" value="表示" action="#{ItemSearch.listItems}" />
            </h:form>
            
            <table border=\"1\">
                <thead><tr><th>ID</th><th>Item</th></tr></thead>
                <tbody>                
                    <c:forEach var="item" items="#{ItemSearch.itemlist}">
                        <tr><td>
                            <h:outputText id="id" value="#{item.id}"/>
                        </td><td>
                            <h:outputText id="name" value="#{item.name}"/> </br>
                        </td><tr>
                    </c:forEach>
                </tbody>
            </table>
        </f:view>
    </body>
</html>

以下にサーバ側プログラムと必要な設定ファイルの例を示す。ここは本題ではないので詳細な解説は省略するが、内容は一般的なJSFのアプリケーションで、プロジェクト名は「Tomcat6JSF」としておく。データを格納するJavaBeanとしてリスト19、JSFのManaged Beanとしてリスト20のようなプログラムを用意する。Managed Beanではデータベースから取得したデータをitemlistプロパティに格納する。

リスト19 データ格納用のJavaBean(Item.java)

package sample;

public class Item {
    private int id;
    private String name;

    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return this.id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
}

リスト20 データベース接続を行うManagedBean(ItemSearch.java)

package sample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;

public class ItemSearch {
    private Collection<Item> itemlist = new ArrayList<Item>();

    public Collection getItemlist() {
        return this.itemlist;
    }

    public String listItems() {
        try {
            Connection con = DriverManager.getConnection
                ("jdbc:derby://localhost:1527/sampledb", "test", "test");
            Statement stat = con.createStatement();
            String sql = "select * from item";
            ResultSet resultSet = stat.executeQuery(sql);
            while(resultSet.next()) {
                Item item =new Item();
                item.setId(resultSet.getInt("id"));
                item.setName(resultSet.getString("name"));
                itemlist.add(item);
            }
        }
        catch (SQLException ex) {
            ex.printStackTrace();
        }
        return "success";        
    }
}

Managed Beanを有効にするためのfaces-config.xmlはリスト21のようになる。また、web.xmlはリスト22のようになった。

リスト21 WEB-INF/faces-config.xml

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

<faces-config version="1.2" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
    <managed-bean>
        <managed-bean-name>ItemSearch</managed-bean-name>
        <managed-bean-class>sample.ItemSearch</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
</faces-config>

リスト22 WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>
            index.jsp
        </welcome-file>
    </welcome-file-list>
</web-app>

これらのファイルをデプロイする際の構成は図26のようになる。これをTomcatにデプロイして「http://localhost/Tomcat6JSF/faces/itemlistJSF.jsp」にアクセスすると、図27のように表示される。この画面で[表示]ボタンをクリックすればデータベースからデータを取得できる(図28)。

図26 ディプロイ後の構成

図27 サンプルプログラムの実行結果

図28 データを取得した結果