ManagedBeanからManagedBeanを呼び出す

今回はManagedBeanから別のManagedBeanを実行する方法について書きます。

JSFのつくりとして1ページ1クラスになるのかなと思います。
その際、別ページへの遷移は別のManagedBeanを呼び出すことになると思います。

JSF2.0の設計思想通りなのかが不安なところですが・・・

【前提条件】

[環境]

【内容】

今回はログイン画面で入力したユーザIDに
紐付くユーザを表示するような画面を作成します。

まずはログイン画面は「index.xhtml」を用意します。
「index.xhtml」は前回と同じです。

<?xml version="1.0" encoding="Windows-31J" ?>
<!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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"> 
    <f:view>
        <h:head>
            <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" />
            <title>ログイン</title>
        </h:head>
        <h:body>
            <h:form id="loginForm">
                <div id="userIdRow">
                    <span id="userIdLabel">ユーザID</span>
                    <span id="userIdInput">
                        <h:inputText id="userId" value="#{indexPage.userId}" />
                    </span>
                </div>
                <div id="passwordRow">
                    <span id="passwordLabel">パスワード</span>
                    <span id="passwordInput">
                        <h:inputSecret id="password" value="#{indexPage.password}" />
                    </span>
                </div>
                <div>
                    <h:commandButton action="#{indexPage.login}" value="ログイン" />
                </div>
            </h:form>
        </h:body>
    </f:view>
</html>

つづいて「index.xhtml」に対応するManagedBeanを作成します。

@ManagedBean(name = "indexPage")
@RequestScoped
public class IndexPageImpl {

    /** メインメニューページ */
    @ManagedProperty(value = "#{resultPage}")
    private ResultPageImpl resultPage = null;

    /** ユーザID */
    private String userId = null;

    /** パスワード */
    private String password = null;

    /**
     * ログイン<br/>
     * ログインに成功した場合:メインメニューに遷移する<br>
     * ログインに失敗した場合:ログイン画面に戻る<br>
     * 
     * @return 画面遷移キー
     */
    @Override
    public String login() {

        System.out.println(userId);
        System.out.println(password);

        return resultPage.init(userId);
    }

    // アクセサメソッドは省略します(ResultPageImplもアクセサメソッドを作成します)
}

前回と変わったところはResultPageImplという違うManagedBeanを作成している点です。
違うManagedBeanを連携させる場合は、
javax.faces.bean.ManagedPropertyアノテーションを使います。

ManagedPropertyアノテーションvalue属性には「#{(ManagedBean名)}とします。

連携させる側のManagedBeanは↓のように作ります。
こちらは通常のManagedBeanとなります。

@ManagedBean(name = "resultPage")
@RequestScoped
public class ResultPageImpl {

    /** ユーザID */
    private String userId = null;

    /** ユーザ名 */
    private String userName = null;

    public String init(final String userId) {

        this.userId = userId;

        if ("test".equals(userId)) {

            userName = "テストユーザ";
        }

        return "resultPage.xhtml";
    }

    // アクセサメソッドは省略します
}

遷移先のページは↓のように作ります。
こちらも通常のJSF2.0に準拠したXHTMLになります。

<?xml version="1.0" encoding="Windows-31J" ?>
<!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:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"> 
    <f:view>
        <h:head>
            <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J" />
            <title>結果画面</title>
        </h:head>
        <h:body>
            <h:form id="loginForm">
                <div id="userIdRow">
                    <span id="userIdLabel">ユーザID</span>
                    <span id="userIdInput">
                        <h:outputText id="userId" value="#{resultPage.userId}" />
                    </span>
                </div>
                <div id="passwordRow">
                    <span id="passwordLabel">ユーザ名</span>
                    <span id="passwordInput">
                        <h:outputText id="userName" value="#{resultPage.userName}" />
                    </span>
                </div>
            </h:form>
        </h:body>
    </f:view>
</html>

今まで書いたのがJSF2.0のみを使った場合になりますが、
CDIを使っても同じことができます。

↑で作ったManagedBeanを少し変えるだけで対応できます。

まず、各ManagedBeanを前回の番外編で書いたとおり
Namedアノテーションとjavax.enterprise.context.RequestScopedアノテーションに書き換えます。

ManagedPropertyアノテーションをjavax.inject.Injectに変更するだけです。

IndexPageImplだけ、変更したバージョンを↓に載せます。
ResultPageImplはクラス宣言のアノテーションを変更するだけです。

@Named(value = "indexPage")
@RequestScoped
public class IndexPageImpl implements IndexPage {

    /** メインメニューページ */
    @Inject
    private ResultPageImpl resultPage = null;

    // 以降は変更前と変わりません
}

Injectアノテーションを使ったほうが名前を指定せずに済みます。