Introduction
In the previous
chapter, EJB's and supporting code were created.
They allow a web application to create a new Person
database record. In this section, the web application
is updated to include a JSF page that allows a
user to enter their details. The information entered
is saved in the database using the EJB's created
in the previous chapter.
The source code is available
in a zip archive here.
Below is a screenshot of
JSF page created in this section:
Create
"register.jsp"
The file called register.jsp
is created in the "src/web" folder.
A previous
chapter which dealt with the welcome page,
explains the tag library, error page and internationalization
bundles. It also explains the form, panelGrid
and facet tags.
The contents of register.jsp
are shown below.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ page errorPage="errorpage.jsp" %>
<f:view>
<f:loadBundle basename="com.j3ltd.web.messages.ApplicationMessages" var="msg"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><h:outputText value="#{msg.pageTitle}"/></title>
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h:form id="registerForm">
<div class="pageTitle"><h:outputText value="#{msg.registration}"/></div>
<br/>
<div class="center">
<h:panelGrid columns="2"
styleClass="form"
headerClass="tableHeader"
footerClass="tableFooter"
rowClasses="tableRowOdd, tableRowEven">
<f:facet name="header">
<h:outputFormat value="#{msg.registrationBoxTitle}">
<f:param value="*"/>
</h:outputFormat>
</f:facet>
<f:facet name="footer">
<h:panelGroup>
<h:commandButton value="#{msg.submit}"
action="#{registrationBean.register}" />
<h:commandButton value="#{msg.reset}" type="reset"/>
</h:panelGroup>
</f:facet>
<h:outputLabel for="title" value="#{msg.registrationTitle}"/>
<h:panelGroup>
<h:inputText id="title" value="#{registrationBean.person.title}"
maxlength="45" size="10"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="title" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="firstName" value="#{msg.registrationName}"/>
<h:panelGroup>
<h:inputText id="firstName" value="#{registrationBean.person.firstName}"
maxlength="255" size="30"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="firstName" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="lastName" value="#{msg.registrationSurname}"/>
<h:panelGroup>
<h:inputText id="lastName" value="#{registrationBean.person.lastName}"
maxlength="255" size="30"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="lastName" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="suffix" value="#{msg.registrationSuffix}"/>
<h:panelGroup>
<h:inputText id="suffix" value="#{registrationBean.person.suffix}"
maxlength="45" size="15"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="suffix" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="dateOfBirth" value="#{msg.registrationDateOfBirth}"/>
<h:panelGroup>
<h:inputText id="dateOfBirth" value="#{registrationBean.person.dateOfBirth}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:inputText> <f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="dateOfBirth" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="gender" value="#{msg.registrationGender}"/>
<h:selectOneRadio id="gender" value="#{registrationBean.person.gender}">
<f:selectItems value="#{registrationBean.genders}"/>
</h:selectOneRadio>
<h:outputLabel for="maritalStatus" value="#{msg.registrationMaritalStatus}"/>
<h:selectOneRadio id="maritalStatus" value="#{registrationBean.person.maritalStatus}">
<f:selectItems value="#{registrationBean.maritalStati}"/>
</h:selectOneRadio>
<h:outputLabel for="line1" value="#{msg.registrationAddress1}"/>
<h:panelGroup>
<h:inputText id="line1" value="#{registrationBean.person.address.line1}"
maxlength="255" size="50"/> <f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="line1" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="line2" value="#{msg.registrationAddress2}"/>
<h:panelGroup>
<h:inputText id="line2" value="#{registrationBean.person.address.line2}"
maxlength="255" size="50"/> <f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="line2" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="line3" value="#{msg.registrationAddress3}"/>
<h:panelGroup>
<h:inputText id="line3" value="#{registrationBean.person.address.line3}"
maxlength="255" size="50"/> <f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="line3" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="line4" value="#{msg.registrationAddress4}"/>
<h:panelGroup>
<h:inputText id="line4" value="#{registrationBean.person.address.line4}"
maxlength="255" size="50"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="line4" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="postcode" value="#{msg.registrationPostcode}"/>
<h:panelGroup>
<h:inputText id="postcode" value="#{registrationBean.person.address.postcode}"
maxlength="50" size="20"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="postcode" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="country" value="#{msg.registrationCountry}"/>
<h:panelGroup>
<h:inputText id="country" value="#{registrationBean.person.address.country}"
maxlength="150" size="40"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="country" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="daytimePhone" value="#{msg.registrationPhoneDay}"/>
<h:panelGroup>
<h:inputText id="daytimePhone" value="#{registrationBean.person.daytimePhone}"
maxlength="45" size="12"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="daytimePhone" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="eveningPhone" value="#{msg.registrationPhoneEvening}"/>
<h:panelGroup>
<h:inputText id="eveningPhone" value="#{registrationBean.person.eveningPhone}"
maxlength="45" size="12"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="eveningPhone" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="email" value="*#{msg.registrationEmail}"/>
<h:panelGroup>
<h:inputText id="email" value="#{registrationBean.person.email}"
maxlength="255" size="50"
required="true">
<f:validator validatorId="EmailValidator"/>
</h:inputText><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="email" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="emailConfirm" value="*#{msg.registrationEmailConfirm}"/>
<h:panelGroup>
<h:inputText id="emailConfirm" value="#{registrationBean.emailConfirm}"
maxlength="255" size="50"
required="true"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="emailConfirm" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="password" value="*#{msg.registrationPassword}"/>
<h:panelGroup>
<h:inputSecret id="password" value="#{registrationBean.person.password}"
maxlength="64" size="20"
required="true" redisplay="true">
<f:validateLength minimum="6"/>
</h:inputSecret><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="password" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="passwordConfirm" value="*#{msg.registrationPasswordConfirm}"/>
<h:panelGroup>
<h:inputSecret id="passwordConfirm" value="#{registrationBean.passwordConfirm}"
maxlength="64" size="20"
required="true" redisplay="true"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="passwordConfirm" styleClass="formUserError"/>
</h:panelGroup>
<h:outputLabel for="webSite" value="#{msg.registrationWeb}"/>
<h:panelGroup>
<h:inputText id="webSite" value="#{registrationBean.person.webSite}"
maxlength="255" size="50"/><f:verbatim><br/></f:verbatim>
<h:outputText value=" "/><h:message for="webSite" styleClass="formUserError"/>
</h:panelGroup>
</h:panelGrid>
</div>
</h:form>
</body>
</html>
</f:view>
The page uses a panelGrid to hold the form with
the input fields. The header facet holds the table's
title, and the footer facet holds the Save and
Reset command buttons.
Every cell which has an input field is wrapped
in a panelGroup. This allows more than one tag
to fit into the cell (column), as should be recalled,
the panelGrid tag expects one child tag per column.
Using panelGroup tags allows the field error message
to appear below the input field to which it refers,
as shown in the screenshot below:
The submit command button calls the register
method on the managed bean (described in the next
section). The register method returns the outcome,
either success or failure, or throws an exception
in an unlikely event that something unexpected
happened.
The Date Of Birth field uses a converter that
is supplied in the core JSF taglib. It allows
JSF to validate and convert the user input into
a java.util.Date.
A custom validator is used on the email field,
it performs simple checks to ensure that the email
entered has a valid syntax.
The password field uses a length validator that
is supplied as part of the core JSF tag library.
The
Register Managed Bean
The JSF page, described in
the previous section, uses the Register managed
bean to get and update data. Below is the code:
package com.j3ltd.web;
import com.j3ltd.common.*;
import com.j3ltd.server.sessionremote.*;
import com.j3ltd.server.entities.*;
import com.j3ltd.server.exceptions.*;
import com.j3ltd.web.messages.*;
import java.util.*;
import javax.faces.context.*;
import javax.faces.application.*;
import javax.faces.model.SelectItem;
import javax.naming.Context;
import javax.naming.InitialContext;
public class Register {
Person person;
private String passwordConfirm;
private String emailConfirm;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public List getGenders() {
ArrayListgenders = new ArrayList();
MessageFactory msg = new MessageFactory();
SelectItem item = new SelectItem();
item.setLabel(msg.getMessage("male"));
item.setValue(Gender.Male.toString());
genders.add(item);
item = new SelectItem();
item.setLabel(msg.getMessage("female"));
item.setValue(Gender.Female.toString());
genders.add(item);
item = new SelectItem();
item.setLabel(msg.getMessage("undisclosed"));
item.setValue(Gender.Undisclosed.toString());
genders.add(item);
return genders;
}
public List getMaritalStati() {
ArrayList maritalStati = new ArrayList();
MessageFactory msg = new MessageFactory();
SelectItem item = new SelectItem();
item.setLabel(msg.getMessage("married"));
item.setValue(MaritalStatus.Married.toString());
maritalStati.add(item);
item = new SelectItem();
item.setLabel(msg.getMessage("single"));
item.setValue(MaritalStatus.Single.toString());
maritalStati.add(item);
item = new SelectItem();
item.setLabel(msg.getMessage("undisclosed"));
item.setValue(MaritalStatus.Undisclosed.toString());
maritalStati.add(item);
return maritalStati;
}
public String register() throws Exception {
String toReturn = "failure";
if (validateData()) {
try {
// save locale information, in case the user chose a language on the welcome page Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); person.setLocaleCountry(locale.getCountry()); person.setLocaleLanguage(locale.getLanguage());
Context context = new InitialContext();
EntityFacade entities = (EntityFacade) context.lookup("EntityFacadeBean/remote");
person = entities.createPerson(person);
toReturn = "success";
}
catch (EntityExistsException exist) {
MessageFactory msg = new MessageFactory();
FacesContext ctx = FacesContext.getCurrentInstance();
ctx.addMessage("registerForm:email",
new FacesMessage(FacesMessage.SEVERITY_ERROR,
msg.getMessage("errorEmailExists"), null));
}
}
return toReturn;
}
/**
* Perform validation that can only be done once
* all the field data is present
* in the person member. Ie: to validate one field
* other field(s) values are needed.
*
* Note that this method creates error messages for the
* faces context, if errors are found.
* @return true if data is OK, false if not OK
*/
private boolean validateData() {
boolean toReturn = true;
MessageFactory msg = new MessageFactory();
FacesContext ctx = FacesContext.getCurrentInstance();
// check emailConfirm is same as email
if (!emailConfirm.equals(person.getEmail())) {
ctx.addMessage("registerForm:emailConfirm",
new FacesMessage(FacesMessage.SEVERITY_ERROR,
msg.getMessage("errorEmailConfirm"), null));
toReturn = false;
}
// check passwordConfirm is same as password
if (!passwordConfirm.equals(person.getPassword())) {
ctx.addMessage("registerForm:passwordConfirm",
new FacesMessage(FacesMessage.SEVERITY_ERROR,
msg.getMessage("errorPasswordConfirm"), null));
toReturn = false;
}
return toReturn;
}
public String getEmailConfirm() {
return emailConfirm;
}
public void setEmailConfirm(String emailConfirm) {
this.emailConfirm = emailConfirm;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
}
The managed bean Register has the members required
to display the JSF page's field data. The Person
entity bean class is used, along with two other
members which are not part of the entity: the
email and password confirmation fields. This illustrates
a new feature in the EJB 3.0 persistence specification:
entity classes passed from an EJB server to a
Web application server are "detached"
from the server. So it is perfectly acceptable
to pass entity beans around as data beans.
The methods getGenders() and getMaritalStati()
return a list that the selectOneRadio tags in
the register.jsp use to display all the options
available.
The method register() is called when the user
submits the page. The method performs last minute
validation, then saves the data using the stateless
EJB defined previously.
The register() method returns the String "success"
if the details were saved, "failure"
if the details could not be saved.
The validateData() method checks that the email
and the email confirmation fields hold the same
value. The same check is made on the password
fields.
Support
Classes
The managed bean, described
in the previous section, uses a few support classes,
these are now described.
An enumeration is used to
describe the possible marital status
of a person, and another enumeration is used to
list the possible genders of
a person. These enumerations are placed in a "com.j3ltd.common"
package, as they may be useful in EJB's and web
applications.
Gender enumeration:
package com.j3ltd.common;
public enum Gender {
Male, Female, Undisclosed
}
Marital status enumeration:
package com.j3ltd.common;
public enum MaritalStatus {
Single, Married, Undisclosed
}
A custom validator class is
defined to validate an email string, it implements
the javax.faces.validator.Validator
interface :
package com.j3ltd.web.utilities;
import javax.faces.validator.*;
import javax.faces.*;
import javax.faces.context.*;
import javax.faces.component.*;
import com.j3ltd.web.messages.*;
import javax.faces.application.*;
public class EmailValidator implements Validator {
public void validate(FacesContext context, UIComponent
component, Object toValidate) {
boolean isValid = true;
String value = null;
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (!(component instanceof UIInput)) {
return;
}
if (null == toValidate) {
return;
}
value = toValidate.toString();
int atIndex = value.indexOf('@');
if (atIndex < 0) {
isValid = false;
}
else if (value.lastIndexOf('.') < atIndex) {
isValid = false;
}
if ( !isValid ) {
MessageFactory msg = new MessageFactory();
FacesMessage errMsg = new FacesMessage(msg.getMessage("errorEmailFormat"));
throw new ValidatorException(errMsg);
}
}
}
A message factory class is defined
to get a localised message from the resource bundles.
This is used by the managed bean:
package com.j3ltd.web.messages;
import java.util.*;
import javax.faces.context.*;
import java.text.*;
public class MessageFactory {
ResourceBundle bundle;
Locale locale;
public MessageFactory() {
locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
bundle = ResourceBundle.getBundle("com.j3ltd.web.messages.ApplicationMessages", locale);
}
public String getMessage(String key) {
return bundle.getString(key);
}
public String getMessage(String key, Object arg1) {
return getMessage(key, new Object[] {arg1});
}
public String getMessage(String key, Object arg1, Object arg2) {
return getMessage(key, new Object[] {arg1, arg2});
}
public String getMessage(String key, Object[] args) {
if (args == null || args.length == 0) {
return bundle.getString(key);
}
MessageFormat fmt = new MessageFormat(bundle.getString(key));
fmt.setLocale(locale);
return fmt.format(args).toString();
}
}
Several getMessage() methods are defined. some
just take the key to find the message in the properties
file. Others take arguments, these are for messages
of the form "this is a message with an argument
{0}". Where the "{0}" denotes where
to put the argument. Internationalization message
bundles were described here.
JSF
Error Messages
JSF provides validation for
input fields: whether the field is mandatory,
the length, data type, format and many other checks,
can all be specified in the JSF page. JSF is installed
with default error messages, it is possible to
override the default messages with our own. This
is done in the message files. Below is the english
message file:
###################
#
# MyCV Application localised text, English
#
###################
pageTitle=MyCV, anytime, anywhere, always there
# Welcome Page
welcome=Welcome To MyCV
welcomeBoxTitle=Please select an option from those listed below
register=Register
login=Login
forgotPassword=Forgot Password
# Registration Page
registration=Register With MyCV
registrationBoxTitle=Fields marked {0} are mandatory.
registrationTitle=Title
registrationName=Name
registrationSurname=Surname
registrationSuffix=Suffix
registrationDateOfBirth=DOB (dd/mm/yyyy)
registrationGender=Gender
registrationAddress1=Address
registrationAddress2=
registrationAddress3=
registrationAddress4=
registrationPostcode=Postcode/Zip
registrationCountry=Country
registrationPhoneDay=Daytime Phone
registrationPhoneEvening=Evening
registrationEmail=Email
registrationEmailConfirm=Confirm Email
registrationPassword=Password
registrationPasswordConfirm=Confirm Password
registrationWeb=Website URL
registrationMaritalStatus=Marital Status
errorGenderString=String value {0} is not a com.j3ltd.common.Gender
errorMaritalStatusString=String value {0} is not a com.j3ltd.common.MaritalStatus
errorGenderObject=Object value {0} is not a com.j3ltd.common.Gender
errorMaritalStatusObject=Object value {0} is not a com.j3ltd.common.MaritalStatus
errorBlankEmail=Please enter a valid email address.
errorEmailConfirm=The email addresses are not the same
errorPasswordConfirm=The passwords are not the same
errorEmailFormat=The email address is not valid
errorEmailExists=The email address is already registered
#Common Page Navigation Labels
submit=Save
reset=Reset
#General Values
english=English
french=Français
married=Married
single=Single
undisclosed=Undisclosed
male=Male
female=Female
# Java conversion and validation error messages, as defined in
# Messages.properties file of JSF
javax.faces.component.UIInput.CONVERSION=the value is incorrect
javax.faces.component.UIInput.REQUIRED=cannot be blank
javax.faces.component.UISelectOne.INVALID=please select a valid option
javax.faces.component.UISelectMany.INVALID=please ensure the option(s) selected are valid
javax.faces.validator.NOT_IN_RANGE=please enter a value between {0} and {1}
javax.faces.validator.DoubleRangeValidator.MAXIMUM=please enter a value less than {0}
javax.faces.validator.DoubleRangeValidator.MINIMUM=please enter a value greater than {0}
javax.faces.validator.DoubleRangeValidator.TYPE=please enter a number
javax.faces.validator.LengthValidator.MAXIMUM=please enter a value shorter than {0} characters
javax.faces.validator.LengthValidator.MINIMUM=please enter a value longer than {0} characters
javax.faces.validator.LongRangeValidator.MAXIMUM=please enter a value less than {0}
javax.faces.validator.LongRangeValidator.MINIMUM=please enter a value greater than {0}
javax.faces.validator.LongRangeValidator.TYPE=please enter a whole number
javax.faces.convert.DateTimeConverter.CONVERSION = Please enter a valid date
The highlighted messages are those used to override
JSF's default messages. A full list of messages
can be found in the JSF jar file: server\default\deploy\jbossweb-tomcat55.sar\jsf-libs\myfaces-impl.jar,
the file is Messages.properties.
Update
The Welcome Page
The original
welcome page does not have any hyperlinks
to the registration page. The file welcome.jsp
is updated to have hyperlinks to the registration
page:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ page errorPage="errorpage.jsp" %>
<f:view>
<f:loadBundle basename="com.j3ltd.web.messages.ApplicationMessages" var="msg"/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><h:outputText value="#{msg.pageTitle}"/></title>
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h:form >
<div class="pageTitle"><h:outputText value="#{msg.welcome}"/></div>
<br/>
<div class="center">
<h:panelGrid columns="3"
styleClass="form"
headerClass="tableHeader">
<f:facet name="header">
<h:outputText value="#{msg.welcomeBoxTitle}"/>
</f:facet>
<h:outputText value="#{msg.login}"/>
<h:commandLink action="register" id="register">
<h:outputText value="#{msg.register}"/>
</h:commandLink>
<h:outputText value="#{msg.forgotPassword}"/>
<h:outputText value=" "/><h:outputText value=" "/><h:outputText value=" "/>
<h:commandLink id="english" action="chooseLocale"
actionListener="#{welcomeBean.onChooseLocale}">
<h:outputText value="#{msg.english}" />
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink id="french" action="chooseLocale"
actionListener="#{welcomeBean.onChooseLocale}">
<h:outputText value="#{msg.french}" />
</h:commandLink>
</h:panelGrid>
</div>
</h:form>
</body>
</html>
</f:view>
Update
The JSF Configuration File
The faces-config.xml file,
originally created in a
previous section, is updated with new navigation
rules for the registration page, and also to specify
the custom validator that has been defined.
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<!DOCTYPE faces-config
PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<application>
<message-bundle>com.j3ltd.web.messages.ApplicationMessages</message-bundle>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>fr</supported-locale>
</locale-config>
</application>
<!--............................ Managed Beans ..........................-->
<managed-bean>
<managed-bean-name>welcomeBean</managed-bean-name>
<managed-bean-class>com.j3ltd.web.Welcome</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>registrationBean</managed-bean-name>
<managed-bean-class>com.j3ltd.web.Register</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>person</property-name>
<value>#{registeringPersonBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>registeringPersonBean</managed-bean-name>
<managed-bean-class>com.j3ltd.server.entities.Person</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
<managed-property>
<property-name>address</property-name>
<value>#{addressBean}</value>
</managed-property>
<managed-property>
<property-name>gender</property-name>
<value>Undisclosed</value>
</managed-property>
<managed-property>
<property-name>maritalStatus</property-name>
<value>Undisclosed</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>addressBean</managed-bean-name>
<managed-bean-class>com.j3ltd.server.entities.Address</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
</managed-bean>
<!--.......................... Navigation Rules ...................-->
<!-- Welcome Page -->
<navigation-rule>
<from-view-id>/welcome.jsp</from-view-id>
<navigation-case>
<description>
Choose locale changes locale then returns to welcome page
</description>
<from-outcome>chooseLocale</from-outcome>
<to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
<navigation-case>
<description>
Navigate to register.jsp
</description>
<from-outcome>register</from-outcome>
<to-view-id>/register.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Registration Page -->
<navigation-rule>
<from-view-id>/register.jsp</from-view-id>
<navigation-case>
<description>
create new user succeeded
</description>
<from-outcome>success</from-outcome>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
<navigation-case>
<description>
create new user failed
</description>
<from-outcome>failure</from-outcome>
<to-view-id>/register.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!--........................... Custom Validators .....................-->
<validator>
<validator-id>EmailValidator</validator-id>
<validator-class>com.j3ltd.web.utilities.EmailValidator</validator-class>
</validator>
</faces-config>
Create
A Login.jsp
A new file called login.jsp
is created in the src/web folder. At the moment
it is used solely to inform us that the register
page saved the details successfully.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ page errorPage="errorpage.jsp" %>
<f:view>
<f:loadBundle basename="com.j3ltd.web.messages.ApplicationMessages" var="msg"/>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title><h:outputText value="#{msg.pageTitle}"/></title>
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h:form >
Registration complete!
</h:form>
</body>
</html>
</f:view>
Package
The Web Application
Several files have been added
to the web application, the Eclipse packaging
configuration for the project's web application
needs to be updated, as described in this section.
The web application packaging
configuration defined in a previous
chapter was basic. The packaging needs to
be updated to exclude the files that only sit
in the EJB server. The packaging also needs to
include files created in this chapter.
Below is a screenshot of
the packaging configuration as it stands:
The entry highlighted above
(/MyCV/bin) is removed.
MyCV.war is right clicked
and "Add Folder" is selected. The project
folder MyCV/bin/com/j3ltd/web
is selected, the prefix given is WEB-INF/classes/com/j3ltd/web.
the includes field is set to **/*.class.
This includes the utilities and messages folders,
as well as the content in the web folder.
The packaging configuration
should look like the one below:
The project packaging is
run to generate the war file.
Deploy
And Test
JBoss is launched in debug
mode from eclipse.
Once JBoss has started, the
ejb archive MyCV.ejb3 is deployed to JBoss, by
right clicking the file in the project explorer
and selecting deployment. The web application
archive MyCV.war is also deployed to JBoss.
A browser is opened, with
the url http://localhost:8080/MyCV.
This brings up the welcome page:
The register hyperlink is
clicked, and the registration page is displayed.
An invalid date, email and password are entered,
then "Save" is clicked, this tests the
date converter, and validators used in the page:
Test values are entered,
as shown below:
The save button is clicked,
which navigates to the rudimentary "login"
page:
MySQL query browser is launched
to check the values that have been inserted into
the database.
The Person table in the shoestring
catalog has been added successfully:
'firstname', 'surname', 1,
'title', 'Male', '1980-12-02 00:00:00', 'suffix',
'dayphone', 'eveningphone', 'http://www.j3ltd.com',
'Married', 1, 'password', 'memail@mail.com', 'en',
''
An address has also been added:
1, 'line1', 'line2', 'line3',
'line4', 'country', 'postcode'
This concludes the registration
process, in this chapter a complete JSF page has
been implemented, it uses a custom validator,
JSF error messages have been overridden and the
EJB 3 entity beans have been implemented to successfully
save data into the database tables, using an EJB
relationship and generated keys.
|