アットウィキロゴ

はじめに

簡単なJSFのプログラミングの紹介です。自分がJDeveloperを使いながらJSFを勉強したときのものを記述しています。なお、理解するためにJDeveloperのGUI機能を敢えて利用していない作業があります。
※JDeveloper10.1.3.2で作業しました。

web.xml

JDevelperで、faces-config.xmlを作成すると、自動的にJSF用のweb.xmlとか書いてくれますが、JSFを利用する場合、FacesServlet(javax.faces.webapp.FacesServlet)の定義が必要です。

<?xml version = '1.0' encoding = 'Shift_JIS'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee">
    <description>Webアプリケーションに対する初期のweb.xmlです。</description>
    <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>35</session-timeout>
    </session-config>
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>txt</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
</web-app>

ページ作成&実行

faces-config.xmlの「ダイアグラム」を開いて、コンポーネント・パレットから「JSF Page」をドラッグします。ここでは、名前は「index.jsp」とします。

そしてindex.jspをダブルクリックして、ウィザードが開きます。基本的にデフォルトでOKですが、「マネージドBeanでUIコンポーネントを自動公開しない」にしておきます。

この段階では faces-config.xml は何も変わっていません。index.jspの定義もないです。
<?xml version="1.0" encoding="Shift_JIS"?>
<!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 xmlns="http://java.sun.com/JSF/Configuration">

</faces-config>

一方index.jspは、次のようになっています。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ 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"%>
<f:view>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"/>
      <title>index</title>
    </head>
    <body><h:form></h:form></body>
  </html>
</f:view>
<@ taglib uri .... がJSFの宣言です。<f:view>タグ範囲に、これからJSFのUIコンポーネントを配置していくことになります。

動作させる場合は、このままだと真っ白画面なので、<h:form>の間にHelloWorldと書いて動かしてみます。(実行は、JSPを選んで右クリックをすると「実行」が選択できます)
    <body><h:form>HelloWorld</h:form></body>
URLが http://...../faces/index.jspのように「faces」を含んでいますが、これは<servlet-mapping>で url-patternを<url-pattern>/faces/*</url-pattern>のように定義しているためです。言い換えれば、javax.faces.webapp.FacesServlet サーブレットクラスを経由しています。


Backing Bean

Backing Beanクラス

Backing Bean(またはManaged Beanと呼ばれる)とは、アプリケーションのWeb層とビジネス層の間のデータ管理に使用されるJavaBeansです。といっても良く分からないかもしれないので、JSPに例えるとuseBean、Strutsで例えるとActionFormに似ています。画面の情報を表すBeanといったところでしょうか。

この後、ログイン画面を作るのでその画面を示すBacking Beanを作ります。

package sample.jsf.bean;

public class Login {

    private String username;
    private String password;

    public Login() {
    }

     public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

faces-config.xml

JavaBeanをJSFのBackingBeanとして認識するために、faces-config.xml を次のように記述します。

<?xml version="1.0" encoding="Shift_JIS"?>
<!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 xmlns="http://java.sun.com/JSF/Configuration">
  <managed-bean>
    <managed-bean-name>LoginBean</managed-bean-name>
    <managed-bean-class>sample.jsf.bean.Login</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
</faces-config>

manage-beanタグに、managed-bean-name、managed-bean-class、managed-bean-scopeを定義します。managed-bean-scopeは、Backing Beanの生存期間を示します。
managed-bean-scope 意味
application そのWebアプリケーションが起動してから終了するまで
session セッションが有効なあいだ
request (HTTPの)要求から応答まで
none スコープには属さない

index.jspに次の記述をします。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ 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"%>
<f:view>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"/>
      <title>index</title>
    </head>
    <body><h:form>
    <table>
    <tr>
     <td nowrap>ユーザ名</td>
     <td><h:inputText id="username" value="#{LoginBean.username}" /></td>
    </tr>
    <tr>
     <td nowrap>パスワード</td>
     <td><h:inputSecret id="password" value="#{LoginBean.password}" /></td>
    </tr>
    </table>
    <h:commandButton value="ログイン" />
    </h:form>
    <p>
    ユーザ名:<h:outputLabel value="#{LoginBean.username}"/>、
    パスワード :<h:outputLabel value="#{LoginBean.password}"/>
    </p>
    </body>
  </html>
</f:view>

<h:inputText>と<h:inputSecret>は、valueに #{LoginBean.username}や#{LoginBean.password} を指定することで、フォームから入力した値がBacking Beanに設定されます。<h:outputLabel>には、Backing Beanの値を出力するようにしています。
ユーザ名とパスワードにaaaa、bbbbを入れて実行すると次のようになります。


画面遷移

faces-config.xml

faces-config.xmlに、<navigation-rule>で画面遷移を定義します。

<?xml version="1.0" encoding="Shift_JIS"?>
<!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 xmlns="http://java.sun.com/JSF/Configuration">
  <managed-bean>
    <managed-bean-name>LoginBean</managed-bean-name>
    <managed-bean-class>sample.jsf.bean.Login</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  <navigation-rule>
    <from-view-id>/index.jsp</from-view-id>
    <navigation-case>
      <from-outcome>success</from-outcome>
      <to-view-id>/success.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
      <from-outcome>failure</from-outcome>
      <to-view-id>/index.jsp</to-view-id>
    </navigation-case>
  </navigation-rule>
</faces-config>

上記は、sucessの場合は success.jsp 画面、failureの場合は index.jsp に戻ることを意味しています。

Backing Beanクラス

Backing Beanクラスに、Strutsで言うところのActionに相当するメソッドを追加します。Webのフォーム画面でSubmitボタンを押下すると呼ばれるメソッドです。

package sample.jsf.bean;
 
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
 
import javax.servlet.http.HttpServletRequest;
 
public class Login {
 
   < setter,getter などは、省略 > 
  
    public String authenticate() {
        if (this.username.equals(this.password)) {
            return "success";
        } else {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ExternalContext externalContext = facesContext.getExternalContext();
            HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
            request.setAttribute("loopback", Boolean.TRUE);
            return "failure";
        }
    }
}

authenticate というメソッドを追加して、ユーザ名とパスワードが同じであれば success を、異なれば failure の文字列を返しています。
また、failure の場合にindex.jsp 側で、失敗したことを判別するために、HttpServletRequest.setAttributeでフラグを渡しています。Backing Beanで、HttpServletRequestのインスタンスを取得する場合、次のように書くと取得できます。
           FacesContext facesContext = FacesContext.getCurrentInstance();
           ExternalContext externalContext = facesContext.getExternalContext();
           HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();

呼び出しフォーム(index.jsp)

Backing Beanのメソッドを呼び出すためにindex.jsp を少し書き換えます。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ 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"%>
<f:view>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"/>
      <title>index</title>
    </head>
    <body><h:form>
    <table>
    <tr>
     <td nowrap>ユーザ名</td>
     <td><h:inputText id="username" value="#{LoginBean.username}" /></td>
    </tr>
    <tr>
     <td nowrap>パスワード</td>
     <td><h:inputSecret id="password" value="#{LoginBean.password}" /></td>
    </tr>
    </table>
    <h:commandButton value="ログイン" action="#{LoginBean.authenticate}" />
    </h:form>
<%
    Boolean loopback = (Boolean)request.getAttribute("loopback");
    if (loopback != null && loopback.booleanValue()) {
%>
    <p><font color="Red">ユーザ名、又はパスワードが間違えています。</font></p>
<%
    }
%>
    </body>
  </html>
</f:view>

先ほど定義したBacking Beanのメソッドを呼び出すために、h:commandButtonタグで次のように定義しています。
    <h:commandButton value="ログイン" action="#{LoginBean.authenticate}" />
また、Backing Beanの authenticate メソッドにおいて、認証に失敗したことを示すsetAttribute("loopback", Boolean.TRUE) しているので、その値を判断するためのロジック を追加しています。

その他

バリデーション

実装方法

ユーザ名、パスワードの入力チェック(バリデート)をしてみます。それぞれ次のような規則とします。

  • ユーザ名 … 必須。最大5文字
  • パスワード … 必須。最小5文字

この規則をJSFのバリデーション機能を利用して実現するために、index.jsp を少し改良します。ユーザ名のh:inputTextタグ を例に説明します。

   <tr>
    <td nowrap>ユーザ名</td>
    <td><h:inputText id="username" value="#{LoginBean.username}" required="true">
    <f:validateLength maximum="5"/></h:inputText></td>
    <td><h:message for="username" /></td>
   </tr>

必須チェックについては、h:inputTextタグ の属性に、require="true" を指定しています。文字の長さチェックは、<f:validateLength maximum="5"/>で指定しています。
バリデートは自分で自作することも可能ですので、既存で用意されているものでは不十分な場合は、開発する方法もあるでしょう。

次に、チェックでエラーになったときの、メッセージは、<h:message for="username" /> の部分で表示されます。<h:messages />でも表示できますが、他のフィールドのメッセージもすべて列挙するので、複数チェック項目がある場合は、どこで間違えたか良く分からないかもしれません。
また、メッセージはJSFで用意している固定のものになりますが、自分でメッセージ作成することも可能です。

h:inputSecrettタグについても基本的にはh:inputTextと同様です。

以下は、改良後の index.jsp 全体です。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ 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"%>
<f:view>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"/>
      <title>index</title>
    </head>
    <body><h:form>
    <table>
    <tr>
     <td nowrap>ユーザ名</td>
     <td><h:inputText id="username" value="#{LoginBean.username}" required="true">
     <f:validateLength maximum="5"/></h:inputText></td>
     <td><h:message for="username" /></td>
    </tr>
    <tr>
     <td nowrap>パスワード</td>
     <td><h:inputSecret id="password" value="#{LoginBean.password}"  required="true">
     <f:validateLength minimum="5"/></h:inputSecret></td>
     <td><h:message for="password" /></td>
    </tr>
    </table>
    <h:commandButton value="ログイン" action="#{LoginBean.authenticate}" />
    </h:form>
<%
    Boolean loopback = (Boolean)request.getAttribute("loopback");
    if (loopback != null && loopback.booleanValue()) {
%>
    <p><font color="Red">ユーザ名、又はパスワードが間違えています。</font></p>
<%
    }
%>
    </body>
  </html>
</f:view>

実行例


  • 必須項目を入力しなかったケース



  • 規定の文字列に従わなかったケース


イベントハンドリング

あとで。
最終更新:2007年09月19日 19:38