JSF2.2入門 第19回CDIとManagedBeanのApplicationScoped(アプリケーションスコープ)

19title

CDIとManagedBeanのどちらにも共通するApplicationScopedについて解説します。ApplicationScopedはWebアプリケーションが有効な期間中で有効なビーンです。一番長い寿命を持つビーンです。

このビーンはアプリケーションがスタートしてからシャットダウンするまでの間生きていて、アプリケーションに所属するJSFページ、JSP、XHTMLからアクセスして情報共有できるのです。当然、アクセスするすべてのユーザーがこのビーンで情報共有できるのです。逆に言えば、すべてのユーザーが共有しても問題がない情報に限られるわけです。よく使われるのは今オンライン状態にあるユーザー数、訪問カウンター、ゲームの最高点、ゲーム結果ベスト10プレイヤーリスト、誰にでも見られて問題ないアンケートや投票、アプリケーションに付随した共通設定などです。
katatsumuri-e1463911702620CDIのApplicationScoped

今回のビーンはアメリカ大統領選挙をイメージした簡単な投票に使ってみます。トランプとクリントンのどちらに投票するか投票用に2つのボタンとその得票数を表示します。

最初にできあがりのイメージを見せたほうがわかりやすいでしょう。

20161111-init

leaf-e1463911721194CDIビーンの書き方

アノーテーションのところがキーポイントです。CDIですからまずは必須の@Namedを付けます。次に@ApplicatioScopedを書きます。それに対応してjavax.enterprise.context.ApplicationScopedをインポートします。ManagedBeanのアプリケーションスコープで使うjavax.faces.bean.ApplicationScopedとは違いますので注意して下さい。Serializableはインプリメントしなくても結構です。プロパティとしてトランプの得票数を保持するtrump、クリントンの得票数を保持するclintonを持っています。

2つのvoidのメソッドがあって、voteTrump()はトランプの得票数を1つ増やすもの、voteClinton()はクリントンの得票数を1つ増やすものです。これはJSFページの中の投票ボタンでコールするものです。

[VoteApplicationBean.java]

package com.myjsf;

import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;

@Named(value=”voteApplicationBean”)
@ApplicationScoped
public class VoteApplicationBean{
private int trump, clinton;
public VoteApplicationBean() {
}

public int getTrump() {
return trump;
}

public void setTrump(int trump) {
this.trump = trump;
}

public int getClinton() {
return clinton;
}

public void setClinton(int clinton) {
this.clinton = clinton;
}
public void voteTrump(){
this.trump++;
}

public void voteClinton(){
this.clinton++;
}
}

leaf-e1463911721194CDIの使い方

レイアウトを整えるためにpanelGridタグを使っています。きれいに2列に整列させるためです。panelGroupタグも使っていますが、これは1つのグループにまとめて1列分として扱いたいためです。ボタンの上にカーソルがきたら色を変えるとか少々複雑なことをスタイルシートでやっていますので、コード全体は「applicationScopeSample.xhtmlの完全なコード」を参照してください。

赤の部分はCDIビーンからそれぞれの得票数を表示している部分です。青のところはそれぞれに投票するためのボタンです。押されたらビーンの票数を1つ増やすメソッドをコールするようそのメソッドをactionListenerに登録しています。

[applicationScopeSample.xhtml]

<h:body>
<center>
<h:form>
<h:panelGrid columns=”2″ columnClasses=”center,center”>
<f:facet name=”caption”>
<h:outputText value=”Presidental Election” styleClass=”center”/>
</f:facet>
<h:panelGroup>
<div class=”t”>TRUMP</div><h:outputText value=”#{voteApplicationBean.trump}”/>
</h:panelGroup>
<h:panelGroup>
<div class=”c”>CLINTON</div><h:outputText value=”#{voteApplicationBean.clinton}”/>
</h:panelGroup>
<h:commandButton value=”Vote Trump” actionListener=”#{voteApplicationBean.voteTrump()}” styleClass=”button”/>
<h:commandButton value=”Vote Clinton” actionListener=”#{voteApplicationBean.voteClinton()}” styleClass=”button”/>
</h:panelGrid>
</h:form>
</center>
</h:body>

leaf-e1463911721194実行してみる

最初にお見せした画面が表示されますので、下のボタンを押すと票数が増えていきます。例えばとトランプの3票、クリントンに1票が投票されたとすると次のようになります。もちろん1人1票とか細かいことは考えていません。実際は必要でしょうけれど。

20161111-votetrump

また、このURLをブラウザーの別のウィンドウでアクセスした場合でも、同じ状態が表示されます。SessionScopedなどではできないことです。このように同じアプリケーションを実行している人なら誰でも同じ情報が共有できるのです。

20161111-others1

katatsumuri-e1463911702620ManagedBeanでのApplicationScoped

同じことをManagedBeanでやってみます。

leaf-e1463911721194ManagedBeanの書き方

まず@ManagedBeanアノーテーションを書きます。次にCDIと同じ@ApplicationScopedを書きますが、これはjavax.faces.bean.ApplicationScopedに定義されているものを意味します。ですのでこれをインポートします。CDIとはパッケージが違います。その他は同じです。

[VoteApplicationBeanMB.java]

package com.myjsf;

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean
@ApplicationScoped
public class VoteApplicationBeanMB{
private int trump, clinton;
public VoteApplicationBeanMB() {
}

public int getTrump() {
return trump;
}

public void setTrump(int trump) {
this.trump = trump;
}

public int getClinton() {
return clinton;
}

public void setClinton(int clinton) {
this.clinton = clinton;
}
public void voteTrump(){
this.trump++;
}

public void voteClinton(){
this.clinton++;
}
}

leaf-e1463911721194ManagedBeanの使い方

これはCDIと同様です。一応次に書いておきます。実行結果は同じですから省略します。

[applicationScopeSampleMB.xhtml]

<h:body>
<h:form>
<h:panelGrid columns=”2″ columnClasses=”center,center”>
<f:facet name=”caption”>
<h:outputText value=”Presidental Election” styleClass=”center”/>
</f:facet>
<h:panelGroup>
<div class=”t”>TRUMP</div><h:outputText value=”#{voteApplicationBeanMB.trump}”/>
</h:panelGroup>
<h:panelGroup>
<div class=”c”>CLINTON</div><h:outputText value=”#{voteApplicationBeanMB.clinton}”/>
</h:panelGroup>
<h:commandButton value=”Vote Trump” actionListener=”#{voteApplicationBeanMB.voteTrump()}” styleClass=”button”/>
<h:commandButton value=”Vote Clinton” actionListener=”#{voteApplicationBeanMB.voteClinton()}” styleClass=”button”/>
</h:panelGrid>
</h:form>
</h:body>

previousnext

JSF2.2のすべてをまとめたkindle電子書籍 「JavaServer Faces2.2 入門」もぜひご覧ください。パソコン、iPhone、Androidどんな端末用にもamazonが無料のKindle電子書籍リーダーを用意しています。それをつかってKindle本を手軽にお楽しみください。あなたが今お使いの端末用Kidle電子書籍リーダーのご案内