3

What happens in the registration process?

This JSF form includes <h:message> tags that will display the results of any JSF validation failures that occur during the form submission cycle.

<div class="entry"> <div class="label"> <h:outputLabel for="username">Username:</h:outputLabel> </div> <div class="input"> <h:inputText id="username" value="#{user.username}"/><br/> <span class="errors"><h:message for="username" /></span> </div> </div> <div class="entry"> <div class="label"> <h:outputLabel for="name">Real Name:</h:outputLabel> </div> <div class="input"> <h:inputText id="name" value="#{user.name}" /><br/> <span class="errors"><h:message for="name" /></span> </div> </div> ... ... <div class="input"> <h:commandButton value="Register" action="#{register.register}" class="button"/> <h:commandButton value="Cancel" action="login" class="button"/> </div>

The form fields are bound to properties of a Seam component named user via JSF EL value binding expressions such as #{user.username}. The form submit button is bound to the register() method of the Seam component named register using the JSF method binding expression #{register.register}.

The User class is an EJB 3.0 entity bean with a @Name annotation that binds the bean instance to a context variable named user. In addition to the standard EJB 3.0 O/R mapping metadata, this bean features several Hibernate Validator annotations such as @NotNull, @Length. These constraints are automatically validated by Seam when the form is submitted. If the user enters invalid data in the JSF form, the form will be redisplayed with error messages.

@Entity @Name("user") @Scope(SESSION) public class User implements Serializable { private String username; private String password; private String name; public User(String name, String password, String username) { this.name = name; this.password = password; this.username = username; } public User() {} @NotNull @Length(max=100) public String getName() { return name; } public void setName(String name) { this.name = name; } @NotNull @Length(min=5, max=15) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Id @Length(min=5, max=15) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }

RegisterAction is an EJB 3.0 stateful session bean bound to the Seam context variable named register. The register() method is invoked when the form is submitted.

@Stateful @Scope(EVENT) @Name("register") public class RegisterAction implements Register { @In @Valid private User user; @PersistenceContext private EntityManager em; @In(create=true) private transient FacesMessages facesMessages; private String verify; @IfInvalid(outcome=REDISPLAY) public String register() { if ( user.getPassword().equals(verify) ) { List existing = em.createQuery("select username from User where username=:username") .setParameter("username", user.getUsername()) .getResultList(); if (existing.size()==0) { em.persist(user); return "login"; } else { facesMessages.add("username #{user.username} already exists"); return null; } } else { facesMessages.add("re-enter your password"); verify=null; return null; } } public String getVerify() { return verify; } public void setVerify(String verify) { this.verify = verify; } @Destroy @Remove public void destroy() {} }

The @In annotations inject Seam components into the RegisterAction bean. The user component is our entity bean, of course. The facesMessages component is a built-in Seam component that makes it very easy to display templated and localized messages to the user, even when redirect after post is used.

The @IfInValid annotation tells the Seam to apply the Hibernate Validator constraints and redisplay the form with error messages if the constraints are violated.