3

What happens in the registration process?

The register.xhtml JSF form captures the user input for new account registration. It validates the user input, binds the data to a Seam data component, and invokes a Seam UI event handler method when the form is submitted.

<s:validateAll> <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> </s:validateAll> ... ... <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}.

Notice that the input fields are enclosed by a <s:validateAll tag. This tag is part of Seam's extension to JSF. It tells the Seam runtime to validate those input fields when the form is submitted. The validation conditions are specified on the entity bean classes those input fields map to (e.g., here the validation condition is on the User class, see later). This JSF form also includes <h:message> tags that will display the results of any JSF validation failures.

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. Due to the <s:validateAll tag in the form, 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 private User user; @PersistenceContext private EntityManager em; @In(create=true) private transient FacesMessages facesMessages; private String verify; 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.