JSF 2.0の新機能AJAXサポートを試す

Glassfish V3とNetBeansの相性が悪い感じなのでJSF実装単体を落としてきてTomcat 6.0で動かしてみた。

例はいつもの足し算のプログラム。

まずはAjaxを使わない通常のJSFのコード。

●faces-config.xml

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

<faces-config version="2.0"
    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_2_0.xsd">

</faces-config>


●newxhtml.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <f:view contentType="text/html"/>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>JSF2.0 Ajax</title>
        <h:outputScript name="jsf.js" library="javax.faces" />
    </head>
    <body>
        <div>
            <h:form id="form">
                <h:inputText id="in1" value="#{hoge.input1}"/>
                +
                <h:inputText id="in2" value="#{hoge.input2}"/>

                <br/>

                <h:commandButton actionListener="#{hoge.action}" value="計算"/>

                <br/>
                
                <h:outputText id="result" value="#{hoge.result}"/>
            </h:form>
        </div>
    </body>
</html>

Hoge.java

package hoge;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;

@ManagedBean
@ViewScoped
public class Hoge implements Serializable{
    int input1;
    int input2;
    String result;

    public int getInput1() {
        return input1;
    }

    public void setInput1(int input1) {
        this.input1 = input1;
    }

    public int getInput2() {
        return input2;
    }

    public void setInput2(int input2) {
        this.input2 = input2;
    }

    public String getResult() {
        return result;
    }

    public void action(ActionEvent evt){
        result = String.format("%d + %d = %d",
                input1,
                input2,
                input1 + input2);
    }
}

今回はスコープをViewScopeにしてみた。これは画面単位でのスコープで、セッションとリクエストスコープの間という使いやすいスコープ。JSF 1.xでは標準になかったが2.0からは標準で入った模様。DWRのscriptスコープやADFのビュースコープと同じか。おそらくJSFで今後一番使われるスコープになると思う。

実行してみる。
まず、初期表示。

そして数値を入力して実行。

URLを見ればわかるとおり普通にフォームのサブミットをしている。


ではこれをAjax対応にしてみよう。ボタンの記述を以下のように変更する。

               <h:commandButton actionListener="#{hoge.action}" value="計算">
                    <f:ajax execute="in1 in2" render="result"/>
                </h:commandButton>|

そして数値を入力して実行。

URLはかわらないし、ボタンを押した後フォーカスが移動していないのがわかる。

executeに指定したIDのコンポーネントAjaxで送信して、renderに更新させたいコンポーネントのIDを指定すればいいらしい。

ためしにexecuteをin1だけにしてみる。

               <h:commandButton actionListener="#{hoge.action}" value="計算">
                    <f:ajax execute="in1" render="result"/>
                </h:commandButton>|

実行。

たしかにin2は送信されていないようだ。

jsf.ajax.requestのショートカットとなっている。
onclickなど好きなイベントに自分でscriptを書くことも可能だ。

参考
https://javaserverfaces.dev.java.net/docs/2.0/jsdocs/symbols/jsf.ajax.html


ちなみにICEfacesAjaxとか何も意識せずに一番最初に書いた通常のフォームのサブミットするコードを書くだけで、変更箇所があればそれを自動で差分レンダリングしてくれる優れもの。