[Subsonic Airlines] 会員登録画面 – バッキングビーンの作成4

バッキングビーンの説明の第4回です。

これまでの記事
設定ファイルの作成
http://subsonic.info/ja/2015/08/23/subsonic-airlines-会員登録画面-設定ファイルの作成/

テンプレートの作成
http://subsonic.info/ja/2015/08/27/subsonic-airlines-会員登録画面-テンプレートの作成/

トップ画面の作成
http://subsonic.info/ja/2015/08/28/subsonic-airlines-会員登録画面-トップ画面の作成/

入力画面の作成
http://subsonic.info/ja/2015/08/31/subsonic-airlines-会員登録画面-入力画面の作成/

バッキングビーンの作成1
http://subsonic.info/ja/2015/09/03/subsonic-airlines-会員登録画面-バッキングビーンの作成1/

バッキングビーンの作成2
http://subsonic.info/ja/2015/09/06/subsonic-airlines-会員登録画面-バッキングビーンの作成2/

バッキングビーンの作成3
http://subsonic.info/ja/2015/09/11/subsonic-airlines-会員登録画面-バッキングビーンの作成3/

ソースコード
https://github.com/subsonicsystems/subsonic-airlines-members

フォーム入力の検証
Java EE 7ではBean Validationが検証機能を提供していますが、今回はBean Validationは使用しないで、検証内容をコードで書いていきます。

Bean Validationを使用すると、モデルにアノテーションを付けるだけで簡単に検証内容を記述できますが、現在のバージョン(1.1)では、検証を細かく制御することができないため、実案件では使いにくい部分があります。

コンポーネントの取得
InputView.javaの68行目でinput.xhtmlのコンポーネントを取得しています。ここでは、form:usernameを指定しているので、input.xhtmlの<h:form id=”form”>の内側の<p:inputText id=”username”/>を取得しています。
次の行のsetValidメソッドは、コンポーネントの検証結果を設定しています。エラーでない場合は、trueを設定します。ここでは、検証前の初期化のためtrueをセットしています。パスワードフィールドも同様にセットしています。

InputView.java

/**
 * Saves User.
 * 
 * @return the outcome.
 * @throws ServletException if an error occurs.
 */
public String save() throws ServletException {
    facesContext = FacesContext.getCurrentInstance();
    UIViewRoot uiViewRoot = facesContext.getViewRoot();
    resourceBundle = ResourceBundle.getBundle("info.subsonic.subsonicairlines.members.web.messages.Messages",
            uiViewRoot.getLocale());

    UIInput usernameUiInput = (UIInput) uiViewRoot.findComponent("form:username");
    usernameUiInput.setValid(true);

    UIInput passwordUiInput = (UIInput) uiViewRoot.findComponent("form:password");
    passwordUiInput.setValid(true);

    boolean isValid = true;

    if (!isUsernameValid()) {
        usernameUiInput.setValid(false);
        isValid = false;
    }

    if (!isPasswordValid()) {
        passwordUiInput.setValid(false);
        isValid = false;
    }

    if (!isValid) {
        return "";
    }

    userService.add(user);

    return "/register/completed";
}

76行目のisUsernameValidメソッドでユーザ名フィールドの検証を行っています。入力エラーの場合は、setValidメソッドでfalseをセットします。falseにセットするとラベルとフォームの枠を赤くして入力エラーであることを示します。パスワードフィールドも同様に検証します。

subsonic-airlines-register-input2

レスポンス
入力にエラーがあった場合、87行目で空文字列を返して処理を終了します。バッキングビーンのメソッドの戻り値は、xhtmlファイル名、または空文字列です。

レスポンスは、AjaxでXMLを返します。戻り値にxhtmlファイル名を指定した場合は、そのxhtmlファイルの内容をXMLに含めます。ブラウザ側では、HTML全体を返ってきたXMLに含まれているHTMLと置き換えます。

戻り値が空文字列の場合は、ブラウザ側では、HTMLの任意の部分を返ってきたXMLに含まれているHTMLと置き換えます。

ここでは、input.xhtmlの30行目のp:commandButtonタグでバッキングビーンを呼び出しており、update=”grid”と指定しているので、<p:panelGrid id=”grid”>と</p:panelGrid>で囲まれた部分が、レスポンスの内容と置き換えられます。レスポンスの内容は、エラー表示の描写を含むフォームとなっています。

/register/input.xml

<!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:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:body>
        <ui:composition template="/WEB-INF/templates/default.xhtml">
            <ui:define name="content">
                <h:outputText value="会員登録"/>
                <p/>
                <h:outputText value="会員情報を入力してください(*は必須項目です)"/>
                <p/>
                <h:form id="form">
                    <p:panelGrid id="grid" columns="3" styleClass="register-input-panel-grid">
                        <p:outputLabel for="username" value="ユーザ名 *"/>
                        <p:inputText id="username" value="#{registerInputView.user.username}"
                                     styleClass="register-input-panel-grid-username-input-text"/>
                        <p:message for="username"/>
                        <p:outputLabel for="password" value="パスワード *"/>
                        <p:password id="password" value="#{registerInputView.user.password}"
                                    redisplay="true" styleClass="register-input-panel-grid-password-password"/>
                        <p:message for="password"/>
                    </p:panelGrid>
                    <div class="height30"></div>
                    <p:panelGrid columns="4" styleClass="register-input-button-panel-grid">
                        <div class="width10"></div>
                        <p:button value="戻る" icon="ui-icon-carat-1-w" outcome="/index"/>
                        <div class="width6"></div>
                        <p:commandButton value="登録" update="grid"
                                         action="#{registerInputView.save()}"/>
                    </p:panelGrid>
                </h:form>
            </ui:define>
        </ui:composition>
    </h:body>
</html>

次回に続きます。