Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

JSF管理対象Beanのスコープを基礎からおさらいしてみる

入社式も終えて数か月後には新人さんが入ってきたりする可能性もあるのですが、新人さんの素朴な質問にハッとすることがちょくちょくあります(^^;
質問に上手く答えられず、あー、意外と自分もちゃんと理解してないなぁ、とか…。

先日、新人さんではないですが後輩(Java EE6開発担当ではない子)から

「今やってるJava EE6開発でのセッション管理っていうか、画面情報の記憶とかってどんな仕組みで管理してるですか?」

と聞かれ、どう答えようか迷いました。

その子はもともとASP.NETのWebForm開発とかをメインにしていたので、主にSession.Contents("key") = value;みたいなのをイメージしていたりして。

アノテーションっていうC#の属性(Attribtue)みたいなのがあって、それで宣言したスコープによってJava EE側が上手いことやってくれてるんだよね…」

みたいな回答の後に、具体例をみせたりしたんですが、何ともわかりにくいような…(-_-;

あとJSFCDIの管理対象Beanの違いとか、うー、みたいな。

こういう説明がちゃんとできない=ちゃんと理解してないんじゃないの>自分、みたいな流れになってスコープを色々確認してみようと思いました(^^;

今の開発ではCDI管理対象Beanをメインにしているので、本当はそっちでやりたいのですが、まずはJSF管理対象Beanでやっています。

JSF2.0のスコープ種類

主に利用するのは4種類だと思いますが、トータルには6種類あるんですね(^^;

  • @ApplicationScoped
  • @SessionScoped
  • @ViewScoped
  • @RequestScoped
  • @CustomScoped
  • @NoneScoped

CustomScopedとNoneScopedはあまり認識がなかったです…。以下サイトより。

作ってみたもの

ボタンを押すとカウントアップする、という単純なWebで動きを確認してみました。
ボタンはページを読み直しするものと、Ajaxで部分更新する2種類設けてます。

JSFのViewはこんな感じで、pタグはPrimeFacesのボタン(Ajax=true)のものです。

<h:form id="reqCntFrm">
    <h:outputText id="reqCnt" value="#{requestScopedCounterBean.count}" />
    <h:commandButton value="カウントアップ" actionListener="#{requestScopedCounterBean.countUp()}" 
                     action="requestScopedCounter.xhtml" />
    <p:commandButton value="カウントアップ" actionListener="#{requestScopedCounterBean.countUp()}" 
                     ajax="true" 
                     update=":reqCntFrm:reqCnt" />
</h:form>  

コードも単純でコンストラクタとsetter/getter、カウントアップするメソッドがあるだけです。スコープに合わせて4つ(request,view,session,application)作りました。

package jp.co.hoge.sessionconfirmation;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name = "requestScopedCounterBean")
@RequestScoped
public class RequestScopedCounterBean implements Serializable{

    private int count;
    
    @PostConstruct
    public void init(){
        count = 0;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
    
    public void countUp(){
        count++;
    }
}

他3つは宣言が

@ManagedBean(name = "viewScopedCounterBean")
@ViewScoped
public class ViewScopedCounterBean implements Serializable {
@ManagedBean(name = "sessionScopedCounterBean")
@SessionScoped
public class SessionScopedCounterBean implements Serializable {
@ManagedBean(name = "appScopedCounterBean")
@ApplicationScoped
public class ApplicationScopedCounterBean implements Serializable{

と違うくらいです。

RequestScoped

まずは一番シンプルなRequestScopedから動かします。
actionListenerでカウントアップされて1となりますが、1回のHTTPリクエストが終わると破棄されるので、再度アクセスしてもカウンタは進みません。どちらのボタンでも同じです。
f:id:kikutaro777:20130407235024j:plain

ViewScoped

次にViewScopedで試します。
まず、画面更新するボタンを押下するとカウントは0から進みません。
actionListenerでカウントアップするも、画面読み直しによりビューが変わるためinitで初期化されてます。
f:id:kikutaro777:20130407235115j:plain

ajax=trueにした部分更新では、ビューとしては同じため、カウントが進みます。
f:id:kikutaro777:20130407235135j:plain

ちなみに新規タブを追加して、URLをコピペすると、セッションは同じでもビューが違うため、新しいカウントで始まります。
f:id:kikutaro777:20130407235222j:plain

SessionScoped

次にSessionScopedを試します。
これはページ読み直し、ajax部分更新、どちらのボタンでもカウントアップします。
f:id:kikutaro777:20130407235238j:plain

さらに新規にタブを追加して、URLをコピペしてもセッションが同じであるためカウントはいきています。
f:id:kikutaro777:20130407235301j:plain

ただし、別のブラウザ立ち上げてセッションが違うような場合は新たなカウントとなります。
f:id:kikutaro777:20130407235328j:plain

ApplicationScoped

アプリケーション全体でキープされるので、ボタンはどちらでもカウントアップするし
f:id:kikutaro777:20130407235342j:plain

タブを追加してもカウントはキープされているし
f:id:kikutaro777:20130407235419j:plain

別のブラウザで立ち上げても、カウントはキープされ、そのままカウントアップも可能です。
f:id:kikutaro777:20130407235432j:plain

CDIで試さなきゃな(^^;

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村