0

Based on the answer from this question, i understand that if there is an error, EJB will throw an exception which will be catch in the backing bean and backing bean will show user an error message based on exception its catch.

My question is, what if theres more than one error? How can i show multiple error message to the user, while the EJB can only throw one exception at a time?

For example, at registration form user will need to input email address, name, password, and re-password, and must not be null. If all the data is valid but the given email address is already exist, EJB will throw EntityExistException and the user will be notified that email address is already registered. What if theres multiple error like password and re-password not match and the name is empty? And i want to show these two error to the user. What exception should EJB throw? What approach i can take to achieve this?

Note: the validation must be in EJB

Community
  • 1
  • 1
Hendra
  • 43
  • 2
  • 10

1 Answers1

2

You shouldn't be doing validation in a backing bean action method, but in a normal Validator.

E.g.

<h:inputText value="#{register.email}" required="true" validator="#{emailValidator}" />
<h:inputSecret binding="#{password}" value="#{register.password}" required="true" />
<h:inputSecret required="true" validator="confirmPasswordValidator">
    <f:attribute name="password" value="#{password.value}" />
</h:inputSecret>
...

with the #{emailValidator} being something like this:

@MangedBean
public class EmailValidator implements Validator {

    @EJB
    private UserService userService;

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value == null) {
            return; // Let required="true" handle.
        }

        if (userService.existsEmail((String) value)) {
            throw new ValidatorException(Messages.createError("Email already exists"));
        }
    }

}

Note that the EJB shouldn't throw an exception here. It should only do that when there's a fatal and unrecoverable error such as DB down or wrong table/column definitions.

And the confirmPasswordValidator being something like this

@FacesValidator("confirmPasswordValidator")
public class ConfirmPasswordValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        Object password = component.getAttributes().get("password");

        if (value == null || password == null) {
            return; // Let required="true" handle.
        }

        if (!password.equals(value)) {
            throw new ValidatorException(Messages.createError("Password do not match"));
        }
    }

}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for your time answering this. But isn't your approach will works for JSF only? What if there is an web service or the web tier is change to struts? Isn't it will make an redundant class for the validation? – Hendra Jun 02 '12 at 14:23
  • Struts has also its own validation API. You can alternatively also use JSR303 bean validation (it are those `@NotNull`, `@Size`, etc annotations). This is designed to be framework independent and already seamlessly integrated in JSF. I'm not sure if an ancient framework like Struts also supports it. After all, EJBs are not intented as validators. They are intented to invoke transactional business tasks. – BalusC Jun 02 '12 at 21:22
  • what if there is an validation that require two attribute at once? like sign in, it require to check the email address and check the password is match or not? did it use validator as well? – Hendra Jun 05 '12 at 04:19
  • Just use one validator. It's by the way poor practice to inform the user if either the email or the password is wrong. Just say that "the login" is wrong. Otherwise it's easy bruteforcing by email for hackers. – BalusC Jun 05 '12 at 04:22