JSF入門

というわけで今日はJSFを触ってみます。とりあえず、環境まわりとちょっとしたサンプルが作れるとよいなぁ。
今回はJSFにはSunのRIを使用します。本当はMyFacesとかTeedaのほうが実践的なのですが*1、今回はコーチング目的なので、標準的なものを教材にする、というのが意図です。

環境

JSFダウンロード

SunのJSFダウンロードページより、JavaServer Faces v1.1.01 Reference Implementationから、「jsf-1_1_01.zip」をダウンロード。

必要なjar

  • commons-beanutils.jar
  • commons-collections.jar
  • commons-digester.jar
  • commons-logging.jar
  • jsf-api.jar
  • jsf-impl.jar
  • jstl.jar(*)
  • standard.jar(*)

(*)はjstlを使用する場合に必要なjarです。

web.xml

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

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

    <!-- Webアプリケーションの名前及び説明 -->
    <display-name>JSF Study</display-name>
    <description>JSF Study</description>

	<!-- コンポーネントツリーをどこに保存するか?
         今のところはclientにするのがよい -->
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <!-- XMLバリデーションをオンにする -->
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- カスタムオブジェクトの確認 falseで問題ない -->
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>

    <!-- Faces Servlet -->
    <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-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
</web-app>		

faces-config.xml

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

<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">

<faces-config>

    <!-- メッセージリソース定義 -->
    <application>
      <message-bundle>bundle.Messages</message-bundle>
      <locale-config>
        <default-locale>ja</default-locale>
        <supported-locale>en</supported-locale>
      </locale-config>
    </application>

    <!-- faces-config.xmlは他にvalidator/converter/component
         を定義できるがここでは割愛 -->

    <!-- backingbean -->
    <managed-bean>
        <managed-bean-name>Hello</managed-bean-name>
        <managed-bean-class>backingbean.HelloBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>hello</property-name>
            <value>Hello World!!</value>
        </managed-property>
    </managed-bean>

    <!-- navigation-rule -->
    <navigation-rule>
        <from-view-id>/greeting.jsp</from-view-id>
        <navigation-case>
            <from-outcome>success</from-outcome>
            <to-view-id>/wellcome.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>

</faces-config>

という感じに書けばOK。managed-bean要素はStrutsでいうところのform-bean要素みたいな感じ。但し、クラス自体はPOJOなのがJSFのよいところですね。
managed-property要素はプロパティの初期化に使用します。上記ではHelloBeanのhelloプロパティに「Hello World!!」という文字列で初期化しています。

JSP

index.jsp
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<!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>index</title>
</head>
<body>
<jsp:forward page="faces/greeting.jsp" />
</body>
</html>

ここではただgreeting.jspにforwardしているだけです。

greeting.jsp
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Hello World</title>
</head>
<body>
<f:view>
<h:form>
<p><h:outputText value="#{Hello.hello}" /></p>
<p><h:commandButton action="#{Hello.wellcome}" value="wellcome!" /></p>
</h:form>
</f:view>
</body>
</html>

はviewのルートになります。JSFで使用される全てのタグのルートに当たるところに必ず記述して下さい。
value属性で指定された文字列をレンダリングします。上記の場合だとHelloBeanのhelloプロパティの値がレンダリングされます。この「#{xxx.xxx}」というのをValueBindingといいます。
はアクションを起こしたい時に使用します。action属性のようにメソッドを呼び出すときに使用する場合はMethodBindingといいます。

クラス

/**
 * BackingBeanサンプル
 */
package backingbean;

/**
 * @author matsuo
 * @version 1.0
 */
public class HelloBean {

    /** Hello */
    private String hello;

    /**
     * @return hello を戻します。
     */
    public String getHello() {
        return hello;
    }

    /**
     * @param hello 設定する hello。
     */
    public void setHello(String hello) {
        this.hello = hello;
    }

    /**
     * wellcomeページへ遷移するメソッド
     * 
     * @return "success"を返してページ遷移
     */
    public String wellcome() {
        return "success";
    }
}

先述のgreeting.jspのMethodBindingでHellBean#wellcomeがコールされます。ここではただ「success」と返しているだけなのでfaces-config.xmlで定義されたようにwellcome.jspに遷移します。

まとめ

まぁ基本はこんな感じです。時間があれば、カスタムコンポーネントの例を示そうと思います。

*1:SunのRIはSCSLというライセンスのため商用利用には向いていない。