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アノテーションを使ったほうが名前を指定せずに済みます。