Challenge Engineer Life !

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

PrimeFacesのAjaxStatusでBlock UI表示処理をまとめる

今一緒に開発している後輩からPrimeFacesのAjaxStatusなるコンポーネントを教えてもらいました(^^;知らなかった。

http://www.primefaces.org/showcase/ui/ajax/status.xhtml

これを上手く使うとBlock UIとかの制御が楽になりそうです。

Block UIは以前の開発で、ボタンの2度押しなどを防ぐために使っていました。


PrimeFaces ExtensionsのBlock UIを利用してみました - Challenge Java EE !

ボタンを押すと

f:id:kikutaro777:20150310211040j:plain

Ajax処理が終わるまで以下のようにBlock UIが表示されて、クリックなどを受け付けません。

f:id:kikutaro777:20150310211046j:plain

当時の開発では、利用したい各ボタンにonstartやoncompleteを付けていて冗長でした。

<h:form id="frm">
    <p:commandButton value="はろー1" actionListener="#{indexBean.hello()}" 
         onstart="PF('blc').show();" oncomplete="PF('blc').hide();" />
    <p:commandButton value="はろー2" actionListener="#{indexBean.hello()}" 
         onstart="PF('blc').show();" oncomplete="PF('blc').hide();" />

    <p:blockUI block="frm" widgetVar="blc" />
</h:form>

AjaxStatusコンポを利用するとAjaxのリクエストをグローバルに一括して扱えて、以下の記述ができます。

<h:form id="frm">
    <!-- ajaxStatusのonstartとoncompleteでBlock UIを呼ぶ -->
    <p:ajaxStatus onstart="PF('blc').show();" oncomplete="PF('blc').hide();" />

    <!-- 各ボタンからはBlock UIのコールを削除 -->
    <p:commandButton value="はろー1" actionListener="#{indexBean.hello()}" />
    <p:commandButton value="はろー2" actionListener="#{indexBean.hello()}" />
    
    <p:blockUI block="frm" widgetVar="blc" />
</h:form>        

おー。

ちなみに「このボタンは対象外にしたいんだけど…」という場合にはglobal属性をfalseにすれば対象外になります。

<p:commandButton value="はろー3" global="false" actionListener="#{indexBean.hello()}" />

前のプロジェクトで使っていたやつを参考に実装を~とお願いしたのですが、こうやってブラッシュアップしてくれるのはいいですねー。助かります。

JSFのAjaxタグのoneventでbegin/complete/successを使う

PrimeFacesに慣れてしまって、通常のHTMLタグでの記述方法がわからなかったりする点があった…ので、メモ。

Ajaxでリクエスト送信のタイミングやレスポンスが戻るタイミングに何らか(JavaScriptなどで)処理を入れたいことがあります。

今回の自分の例では、テキストのフォーカスアウト時にAjaxで処理を開始してからレスポンスが戻るまでの間に画面操作をブロックしたい。というものでした。

リクエストの送信時にブロックUIを出して、レスポンス受信時にブロックUIを解除する、イメージです。

画面で説明すると

テキストがあって

f:id:kikutaro777:20130828203939j:plain

文字を入力

f:id:kikutaro777:20130828204053j:plain

フォーカスアウトするとAjaxで処理を呼び出して、その間は画面ブロック

f:id:kikutaro777:20130828184214j:plain

Ajaxのレスポンスが戻った時点でブロックが消えて画面が操作できる流れです。

で、通常こうした処理ではAjaxタグにあるonevent属性を使うようです。
以下、実際にお試しで書いたビュー↓

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:pe="http://primefaces.org/ui/extensions"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head>
        <title>フォーカスブロックのサンプル</title>
    </h:head>
    <h:body>
        <h:form id="frm">
            <!-- PrimeFaces ExtensionのBlockUIコンポーネント -->
            <pe:blockUI target="frm" widgetVar="blc">
                <h:panelGrid columns="2">
                    <p:graphicImage id="imgLoaderBlc" library="images" 
                       name="ajax-loader.gif" width="15px" height="15px"/>
                    <h:outputLabel id="lblBlcProcessing" 
                       value="処理中だよー" style="font-size: 0.6em;"/>
                </h:panelGrid>
            </pe:blockUI>

            <!-- 入力テキストとAjaxによるチェンジイベント -->
            <h:inputText id="txtInput" value="#{indexBean.inputVal}">
                <f:ajax event="change" listener="#{indexBean.calc()}" render="@form" 
                   onevent="focusBlock" />
            </h:inputText>
        </h:form>
        
        <!-- Block UIの呼出し -->
        <script type="text/javascript">
            function focusBlock(data){
                var ajaxStatus = data.status;

                //statusで処理を振り分ける
                switch(ajaxStatus){
                    //beginだったらブロックUIを表示
                    case "begin":
                        blc.block();
                        break;
                    //completeだったらブロックUIを解除
                    case "complete":
                        blc.unblock();
                        break;
                }
            }
        </script>
    </h:body>
</html>

ajaxタグのonevent属性でJavaScriptの処理を呼びますが、その中でstatusをみてbegin/completeの処理を書いてます。同じようにsuccessも使えるようです。

知らなかった…(^^;

ちなみにPrimeFacesを利用しているとJavaScriptの記述が不要でInputTextの部分が以下のように書けます。

<p:inputText id="pTxtInput" value="#{indexBean.inputVal}">
    <p:ajax event="change" listener="#{indexBean.calc()}" update="@form" 
       onstart="blc.block();" oncomplete="blc.unblock();" />
</p:inputText>

PrimeFacesの拡張Ajaxタグだとupdate属性が通常のrender属性にあたり、さらに属性でonstart/oncompleteが指定できます。さらにonsuccessも存在します。

実行すると同じです。(ただし以下はテキストもPrimeFacesのコンポ)

f:id:kikutaro777:20130828184518j:plain

JavaScript書かないし、記述はかなり楽です。

が、JSFの標準的な記述をちゃんと勉強せねば…と痛感(^^;

なお、今回の参考資料は

でした。さすが。

JSFのデバッグって…?

最初に結論を書いておくと

JSFデバッグではこれで完璧だ!

というエントリではないです(^^;

自分がやってることをまとめたレベルで、むしろ皆どうやってるんだろ…的な(^^;

……

前回のJava EE 6開発でちょこちょこハマった点の1つに、JSFのビューが思うようにいかない…というのがありました。

しょぼいミスによるエラーとしては例えば

  • IDの指定が重複している
  • IDの指定が間違っている

とかですね(^^;

具体的には以下のような記述ですが、実行するとこれらはわかりやすいエラーとなるので問題ないです。

IDの指定が重複している例
<h:inputText id="txtInput" value="#{indexBean.inputText}" />
<!-- さすがにこんな近さでIDが重なるのは少ないけど、色々なものを挟んだ場合など -->
<h:inputText id="txtInput" value="#{indexBean.inputText2}" />
IDの指定が重複している場合のエラー

f:id:kikutaro777:20130809220749j:plain

IDの指定が間違っている例
<h:inputText id="txtInput" value="#{indexBean.inputText}" />
<h:commandButton value="送信">
    <f:ajax execute="txtImput" />  <!-- 正しくは mじゃなくn -->
</h:commandButton>
IDの指定が間違っている場合のエラー

f:id:kikutaro777:20130809220757j:plain

なぜかこっちは英語…(-_-;

エラーがわかりにくいときもありますが、まあまだ良い方かなと。

ハマるエラー

上記のように明確なエラーとならない場合にハマったりします。例えばですが

  • ある一部分以降がうまく描画されない
  • データと画面描画の更新してるけど反映されない
  • Ajaxが思ったように動かない

などなど…。

そういうとき自分がやっていたこととしては

  • APサーバのエラー出力確認
  • ブラウザの開発者ツール等で生成されたHTMLやAjax通信などを確認
  • <ui:debug>タグ

辺りでしたが、決め手に欠く感じ…(^^;

APサーバのエラー出力確認

まあベタですが…(^^;
NetBeansGlassFish使っている場合には、以下のGlassFishのコンソールとかです。
まずはここで何かエラーが出てないかチェックしてました。

f:id:kikutaro777:20130809221404j:plain

ブラウザの開発者ツール等で生成されたHTMLやAjax通信などを確認

主観ですが…これが全てにおいて最も効果的なんじゃないかなと(^^;
もはやJSF関係ないですが…。

主に使っていたツールは

辺りです。

レンダリングが途中からうまくできてない、とか、コンポーネントのID確認などはFirebugChrome Developer Toolsを使うと以下のようにタグと実画面のハイライトが連動するのでタグ特定しやすいです。

Firebug
f:id:kikutaro777:20130809223159j:plain
Chrome Developer Tools
f:id:kikutaro777:20130809223206j:plain

Ajaxまわりも同様ですね。レスポンスのステータスや内容を確認したり。

Firebug
f:id:kikutaro777:20130809223807j:plain
Chrome Developer Tools
f:id:kikutaro777:20130809223812j:plain
Fiddler2
f:id:kikutaro777:20130809224112j:plain

IEの開発者ツールはIEのバージョンを変えて確認する場合によく使いました。
f:id:kikutaro777:20130809230318j:plain

ってホントJSF関係ないや(ノД`)

<ui:debug>タグ

で、やっとこJSF特有な情報(^^;

ビューの適当なところに<ui:debug>タグを埋め込みます。
例えば以下のような感じ。

<h:body>
    <h:form id="frm">
        <h:panelGrid id="pg" columns="2">
            <h:inputText id="txtInput" value="#{requestScopedBean.inputRequestScopedVal}" />
            <h:inputText id="txtInput" value="#{viewScopedBean.inputViewScopedVal}" />
            <h:commandButton value="送信">
                <f:ajax execute="txtInput" />
            </h:commandButton>
        </h:panelGrid>
    </h:form>
</h:body>
    
<ui:debug/> <!-- ←これ -->

デフォルトではブラウザ上で

Ctrl + Shift + d

と押すことでJSFデバッグウィンドウが起動します。
f:id:kikutaro777:20130809225019j:plain

で、JSFコンポーネントツリーを確認できたり
f:id:kikutaro777:20130809225039j:plain

スコープ別にBackingBeanの確認ができたり
f:id:kikutaro777:20130809225245j:plain

ちなみに、Chromeでは上記ショートカットが使われているので、定義を

<ui:debug hotkey="x"/>

などとして、ホットキーを割り当てすると楽です。これで

Ctrl + Shift + x

で起動することができます。

あと、これはあくまでもデバッグ用なので、rendered属性を使ってProduction環境では使えないようにする、とか工夫が必要となるので注意です。以下サイトなどが具体例の1つかと。

と、こんなタグがありますが、個人的にはこれが役に立った記憶があまりないです…(-_-;

どなたか「この<ui:debug>があるからこれこれが嬉しいじゃないか!」というのがあれば是非(^^;

というわけで、皆JSFデバッグってどうやってるのかしら…と。

他に何かいい手があるのかなー。

PrimeFacesのボタンでAjaxとimmediateが絡んでキャンセルボタンが上手く動作しない時

わかりにくいタイトルですみません(^^;

JSFで必須バリデーションなどを無視して画面遷移したい場合(戻るボタン、みたいな)、通常はCommandButtonの属性にあるimmediateをtrueにして回避することがあると思います。

自分も今までこれで問題なく進んできたのですが、今日、上手く対応できないケースがありました。
具体的には

  • ajaxを利用しているCommandButton
  • 同一の画面内で更新

のケースです。画面遷移するようなケースは問題ないのですが、上記は駄目でした。

簡単なサンプル作ったら再現できたので以下に具体例を載せます。
まずは話をわかりやすくするため、普通の例から並べてみます。

入力フォームがあって、入力をキャンセルする

例えば…ですが、何かの入力項目があって、そこに文字を入れたけど、キャンセルして空白にする、みたいなケースです。

イメージは下図のような感じでテキストとボタンがあって
f:id:kikutaro777:20130510192421j:plain

テキストに何か文字を入れます
f:id:kikutaro777:20130510192439j:plain

ボタン押すとクリアされます
f:id:kikutaro777:20130510192504j:plain

JSFは以下です。actionListenerでBackingBeanのcancelメソッドを実行してますが、この中身は単にinputValueにnullを入れてるだけです。

<h:form id="frm">
    <p:inputText id="txtInput" value="#{requiredCancelBean.inputValue}" />
    <p:commandButton id="btnCancel" value="Cancel"
                     actionListener="#{requiredCancelBean.cancel()}"
                     update="@form" />
</h:form>

これはシンプルな例なので問題ないです。続けて。

必須項目が存在した場合

もう1つテキストを加えて、それを必須とします。required = trueです。

左に必須のテキストが追加された状態でてくるので、先と同じようにテキストに文字入力します。
f:id:kikutaro777:20130510192640j:plain

この状態でキャンセルボタンを押すと…バリデーションエラーになります(わかりにくいですが下図で左のテキストが赤くなってます)。
f:id:kikutaro777:20130510192711j:plain

ここまでは当たり前な流れですね(^^;

JSFは以下。

<h:form id="frm">
    <!-- 必須項目追加 -->
    <p:inputText id="txtRequiredInput" required="true" value="#{requiredCancelBean.inputReqValue}" />

    <p:inputText id="txtInput" value="#{requiredCancelBean.inputValue}" />
    <p:commandButton id="btnCancel" value="Cancel"
                     actionListener="#{requiredCancelBean.cancel()}"
                     update="@form" />
</h:form>
immediateの登場

で、immediateフラグをtrueにします。すると

f:id:kikutaro777:20130510193715j:plain

f:id:kikutaro777:20130510193725j:plain

必須のエラーは引っかからなくなった!!!けれども、今度は文字が消されない!!

なんで!ってことで、困ったときのstackoverflowへ…。

ちなみに今のjsfは以下です。

<h:form id="frm">
    <!-- 必須項目追加 -->
    <p:inputText id="txtRequiredInput" required="true" value="#{requiredCancelBean.inputReqValue}" />

    <p:inputText id="txtInput" value="#{requiredCancelBean.inputValue}" />
    <p:commandButton id="btnCancel" value="Cancel"
                     actionListener="#{requiredCancelBean.cancel()}"
                     update="@form" 
                     immediate="true"/>
</h:form>
asyncとprocess属性

StackOverflowにやはり同じようなQAがありました。

JSF immediate=“true” for cancel button doesn't work

immediateは「戻る」ボタンみたいに、ビューが変わるのには良いですが、同一のビュー、かつajaxを利用した場合にはイマイチ問題があるようです。ほぉ…。

で、サンプルにあったのはasyncをtrueにして、processに@thisを指定するというもの。

先にJSFに追加してみました。

<h:form id="frm">
    <!-- 必須項目追加 -->
    <p:inputText id="txtRequiredInput" required="true" value="#{requiredCancelBean.inputReqValue}" />

    <p:inputText id="txtInput" value="#{requiredCancelBean.inputValue}" />
    <p:commandButton id="btnCancel" value="Cancel"
                     actionListener="#{requiredCancelBean.cancel()}"
                     update="@form" 
                     immediate="true"
                     async="true"
                     process="@this"/>
</h:form>

で実行すると

f:id:kikutaro777:20130510194020j:plain

f:id:kikutaro777:20130510194025j:plain

おー、ちゃんと実行された。なんだこれ。
User Guide読むとasyncはajaxのリクエストをキューしないようにするもので、processはビュー全体更新の代わりに部分的に処理する、みたいに書いてありますがイマイチちゃんと理解できてない(^^;

こういう細かい所、JSFAjaxの関連含めてしっかり理解して使いたいなぁ…と思いながら、ついつい入れてしまいました…。

JSFでコンポーネントをプログラムから動的に生成する ~イベント利用~

先日書いた「JSFでコンポーネントをプログラムから動的に生成する」の続きです。

※とある技術調査でやっている実験なので、参考程度でお願いします(^^;

先日のサンプルを改造して、さらに1つ、パネル+プルダウンをプログラムから生成して、片方のプルダウンを選択したイベントで、もう片方のプルダウン内容を変える、ことをやってみました。

言葉だけだとイマイチなので結果の画像を載せると

2つのパネル+プルダウンがそれぞれプログラムから生成されて

f:id:kikutaro777:20130421231440j:plain

片方を選択したイベントで

f:id:kikutaro777:20130421231448j:plain

もう片方のプルダウンの中身が変わる

f:id:kikutaro777:20130421231455j:plain

これだけですが、イベント自体もプログラムで定義しています(^^;
ビューはほとんど定義してなくて、全てプログラムっていう…。

通常、プルダウンのイベントはPrimeFacesを利用している場合

<p:selectOneMenu >
    <p:ajax event="change" listener="#{hogeBean.hogeMethod}" update="@form" />
    <f:selectItems value="#{hogeBean.hogeList" />
</p:selectOneMenu>

のように書きます(ajaxタグを利用しない場合はselectOneMenuのvalueChangeListenerを利用)

これをプログラムで書くとどうなるんだ…と調べてみたところ、結構やろうとする人がいるのか、情報はそこそこにありました。

で、AjaxBehaviorを使えば良さそうとわかったのですが、実際には上手く動きませんでした(-_-;なんかPrimeFacesのForumとかStackOverflowでもチラホラ「動かない」といってる人がいたけど、珍しく良い回答がなかったです。

で、試行錯誤してたら、ValueChangeListenerなら動きました。ただSelectOneMenuにはupdate属性が存在しないため、そこはAjaxBehaviorを定義したら何か一応できた(^^;けど色々怪しげ。

該当コード抜粋するとこんな感じです。

//Ajaxイベントを生成 EL式でBackingBeanのメソッドを紐づける
AjaxBehavior selectEvent = new AjaxBehavior();
ELContext elCtx = FacesContext.getCurrentInstance().getELContext();
ExpressionFactory expFact = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
String el = "#{hogeBean.changeItems()}";
selectEvent.setUpdate("@form");

//Ajaxイベントをプルダウンに紐付け
codingPullDown2.addClientBehavior("change", selectEvent);
        
//上記のAjaxイベントだけで完結したいが、うまく動かなかったのでValueChangeListener利用
ValueChangeListener changeListener = new MethodExpressionValueChangeListener(expFact.createMethodExpression(elCtx, el,String.class, new Class[]{String.class}));

//ValueChangeListener紐付け        
codingPullDown2.addValueChangeListener(changeListener);

で、Backing BeanにchangeItems()を定義して、中身を入れ替える処理をとりあえずベタに書きます。

public void changeItems(){
    List<SelectItem> newItems = new ArrayList<>();
    newItems.add(new SelectItem("newKey1", "イベントで入れ替わった項目1"));
    newItems.add(new SelectItem("newKey2", "イベントで入れ替わった項目2"));
    newItems.add(new SelectItem("newKey3", "イベントで入れ替わった項目3"));
        
    //UISelectItemsにアイテムをセット
    UISelectItems selectItems = new UISelectItems();
    selectItems.setValue(newItems);
        
    //既に生成されたプルダウンを取得
    SelectOneMenu codingPullDown = (SelectOneMenu)FacesContext.getCurrentInstance().getViewRoot().findComponent(":frmDg:pdmCoding");

    //既存プルダウンアイテムを一掃して
    List<UIComponent> removeList = codingPullDown.getChildren();
    codingPullDown.getChildren().removeAll(removeList);
        
    //新たに追加
    codingPullDown.getChildren().add(selectItems);
}

技術調査とはいえ、JSFでビューをほとんど定義せずにプログラムで生成して、さらにイベントも…ってなると、やはり複雑になるので、あまりやりたくないなぁと。。。

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で試さなきゃな(^^;

PrimeFacesで上手く動かないときはFirebugで確認する

少し前のエントリ「NetBeansのHTTPサーバ・モニターに触れる」でHTTPパケットをチェックすることを書きましたが、PrimeFacesを使っていてよくチェックすることがもう1つありました。

Ajaxのエラーです。

PrimeFacesを使って少し入り組んだことをやろうとすると、稀に「動いているようにみえるけど、動いていない」状態に出会います。なんか表現が変ですが(^^;

GlassFish上、エラーも出てないし、画面的にもエラー出てないのに、思ったように動かないようなケースです。

具体的にどういうケースか忘れてしまったのですが、当時は最初何が起きたかわからず、少し焦った記憶があります。

で、それ以降、こうした現象に出会った場合には、必ずFirefoxのアドオンである「Firebug」を起動してチェックするようにしています。上記のようなエラーだとAjax内部でエラーが起きているケースだったりするので…(^^;

f:id:kikutaro777:20130323234408j:plain

多分、Web開発者的には、ごくごく当たり前のことなのだと思いますが、自分のようにWindows Form開発ばかりやってきて、Web開発経験がない+なぜか周りに詳しい人がいない…、場合には意外とこんなしょうもないことで最初につまづいたりしてしまいます。修業あるのみ。

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