ConversationScopedについて

jsf jsf
cdi CDI

@ConversationScopedはブラウザとサーバー間で何往復かする間だけオブジェクト(バッキングビーン)が存続します
そのため、開始と終了をプログラマが指定する必要があります

今回は簡単に会話スコープを試せるサンプルを紹介します

サンプルの画面遷移

画面関係図.png

「start」ボタンを押した時、会話スコープが開始します
商品選択、顧客情報入力画面で注文情報を入力し、注文確認画面で確認します
「購入」ボタンを押すと会話処理を終了してトップページへ戻ります

会話処理の開始と終了

バッキングビーンのソースコード

import java.io.Serializable;

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

@SuppressWarnings("serial")
@Named
@ConversationScoped
public class SampleConversation implements Serializable {
    //商品名
    private String product;
    //数量
    private Integer quantity;
    //氏名
    private String name;
    //住所
    private String address;

    @Inject
    Conversation conv;

    public String toProduct() {
        if (conv.isTransient()) {
            conv.begin();
        }
        return "product.xhtml";
    }

    public String toClient() {
        return "client.xhtml";
    }

    public String toConfirmation() {
        return "confirmation.xhtml";
    }

    public String toTop() {
        conv.end();
        return "top.xhtml";
    }

    //Getter と Setter (省略)    
}

会話スコープでは、クラスに@ConversationScopedアノテーションをつけます
会話スコープは会話スコープマネージャーを使って、プログラムの開始と終了を行います
CDIサービスから会話スコープマネージャーをインジェクトで取得します

   @Inject
   Conversation conv;

トップページで「start」ボタンが押されるとtoProduct()メソッドを実行し、会話スコープが開始されます

   if (conv.isTransient()) {
       conv.begin();
   }
   return "product.xhtml";

conv.isTransient()ですでに会話スコープが始まっていないことを確かめてからスタートします
注文確認画面までは会話スコープの中なので、入力したデータは継続して使用できます
前の画面に戻ってもデータが保持されていることを確認してください
そして注文確認画面の「購入」ボタンを押すと、会話スコープが終了します

   conv.end();
   return "top.xhtml";

endメソッドは会話スコープを終了します
それによりトップページへ遷移するとバッキングビーンは廃棄されます

JSFページの内容

top.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <title>会話スコープ</title>
</h:head>
<h:body>
    <h1>TOP</h1>
    <h:form>
        <h:commandButton action="#{sampleConversation.toProduct()}" value="start" />
    </h:form>
</h:body>
</html>

product.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <title>会話スコープ</title>
</h:head>
<h:body>
    <h1>商品選択</h1>
    <h:form>
        <h:panelGrid columns="2">
            商品名<h:inputText value="#{sampleConversation.product}" />
            数 量<h:inputText value="#{sampleConversation.quantity}" />
            <h:commandButton action="#{sampleConversation.toTop()}" value="キャンセル" />
            <h:commandButton action="#{sampleConversation.toClient()}" value="顧客情報入力へ" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>

client.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <title>会話スコープ</title>
</h:head>
<h:body>
    <h1>顧客情報入力</h1>
    <h:form>
        <h:panelGrid columns="2">
            お名前<h:inputText value="#{sampleConversation.name}" />
            ご住所<h:inputText value="#{sampleConversation.address}" />
            <h:commandButton action="#{sampleConversation.toProduct()}" value="戻る" />
            <h:commandButton action="#{sampleConversation.toConfirmation()}" value="注文確認へ" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>

confirmation.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <title>会話スコープ</title>
</h:head>
<h:body>
    <h1>注文確認</h1>
    <h:form>
        <h:panelGrid columns="2">
            商品名<h:outputText value="#{sampleConversation.product}" />
            数 量<h:outputText value="#{sampleConversation.quantity}" />
            お名前<h:outputText value="#{sampleConversation.name}" />
            ご住所<h:outputText value="#{sampleConversation.address}" />
            <h:commandButton action="#{sampleConversation.toClient()}" value="戻る" />
            <h:commandButton action="#{sampleConversation.toTop()}" value="購入" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>