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

今回から複数回にわたって、バッキングビーンについて説明します。

これまでの記事
設定ファイルの作成
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-会員登録画面-入力画面の作成/

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


info.subsonic.subsonicairlines.members.view.register.InputView.java

package info.subsonic.subsonicairlines.members.view.register;

import info.subsonic.subsonicairlines.members.model.User;
import info.subsonic.subsonicairlines.members.service.UserService;

import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;

import org.apache.commons.lang3.StringUtils;

/**
 * This class is for register input view.
 */
@Named("registerInputView")
@RequestScoped
public class InputView {

    /**
     * The UserService.
     */
    @Inject
    private UserService userService;

    /**
     * The User.
     */
    private User user;

    /**
     * The FacesContext.
     */
    private FacesContext facesContext;

    /**
     * The ResourceBundle.
     */
    private ResourceBundle resourceBundle;

    /**
     * Initializes.
     */
    @PostConstruct
    public void init() {
        user = new User();
    }

    /**
     * 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";
    }

    /**
     * Gets User.
     *
     * @return the User.
     */
    public User getUser() {
        return user;
    }

    /**
     * Sets User.
     *
     * @param user the User.
     */
    public void setUser(User user) {
        this.user = user;
    }

    /**
     * Tests if username is valid.
     * 
     * @return true if username is valid; false otherwise.
     */
    private boolean isUsernameValid() {

        if (StringUtils.isBlank(user.getUsername())) {
            String message = resourceBundle.getString("user.username.required");
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:username", facesMessage);
            return false;
        }

        if (!user.getUsername().matches(User.USERNAME_REGEXP)) {
            String message = resourceBundle.getString("user.username.invalid");
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:username", facesMessage);
            return false;
        }

        if (user.getUsername().length() < User.USERNAME_MIN_LENGTH) {
            String message = resourceBundle.getString("user.username.minLength");
            message = message.replace("{min}", String.valueOf(User.USERNAME_MIN_LENGTH));

            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:username", facesMessage);
            return false;
        }

        if (user.getUsername().length() > User.USERNAME_MAX_LENGTH) {
            String message = resourceBundle.getString("user.username.maxLength");
            message = message.replace("{max}", String.valueOf(User.USERNAME_MAX_LENGTH));
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:username", facesMessage);
            return false;
        }

        if (userService.existsUsername(user.getUsername())) {
            String message = resourceBundle.getString("user.username.exists");
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:username", facesMessage);
            return false;
        }

        return true;
    }

    /**
     * Tests if password is valid.
     * 
     * @return true if password is valid; false otherwise.
     */
    private boolean isPasswordValid() {

        if (StringUtils.isBlank(user.getPassword())) {
            String message = resourceBundle.getString("user.password.required");
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:password", facesMessage);
            return false;
        }

        if (!user.getPassword().matches(User.PASSWORD_REGEXP)) {
            String message = resourceBundle.getString("user.password.invalid");
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:password", facesMessage);
            return false;
        }

        if (user.getPassword().length() < User.PASSWORD_MIN_LENGTH) {
            String message = resourceBundle.getString("user.password.minLength");
            message = message.replace("{min}", String.valueOf(User.PASSWORD_MIN_LENGTH));
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:password", facesMessage);
            return false;
        }

        if (user.getPassword().length() > User.PASSWORD_MAX_LENGTH) {
            String message = resourceBundle.getString("user.password.maxLength");
            message = message.replace("{max}", String.valueOf(User.PASSWORD_MAX_LENGTH));
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
            facesContext.addMessage("form:password", facesMessage);
            return false;
        }

        return true;
    }

}

@Named
@Namedは、EL式で参照する名称を定義します。

@Named("registerInputView")
@RequestScoped
public class InputView {

ここでは、registerInputViewと定義しているので、EL式でregisterInputViewを指定すると、InputView.javaを参照できるようになります。

例えば、/register/input.xhtmlでは、次のように使用されています。

<p:commandButton value="登録" update="grid"
                 action="#{registerInputView.save()}"/>

この場合、InputView.javaのsaveメソッドが呼ばれます。

スコープ
スコープは、バッキングビーンの生存期間を定めます。

@RequestScoped
public class InputView {

ここでは、@RequestScopedが定義されていますが、@RequestScopedは2つあります。

ひとつは、javax.enterprise.context.RequestScopedで、もうひとつはjavax.faces.bean.RequestScopedです。前者は、CDIのパッケージで、後者はJSFです。

これらの使い分けについては、どちらを使っても機能としては同じなのですが、将来のJava EEのバージョンでは、前者に統一するようなので、これから新規に開発するのであれば、前者を使用するのがよいと思います。

以前の記事もご参照ください。
http://subsonic.info/ja/2015/07/27/java-ee-7-スコープについて/

主なスコープの生存期間は、次の通りです。

スコープ 生存期間
javax.enterprise.context.RequestScoped 1ユーザの1回のHTTPリクエストの間
javax.enterprise.context.SessionScoped 1ユーザの複数回のHTTPリクエストの間
javax.enterprise.context.ApplicationScoped すべてのユーザによって状態が共有されます

次回に続きます。