The Java EE 5 Tutorial

JSP Pages

The JSP pages are as follows:

The orderForm Page

orderForm displays the current contents of the shopping cart. The first time the page is requested, the quantities of all the coffees are 0 (zero). Each time the customer changes the coffee amounts and clicks the Update button, the request is posted back to orderForm.

The CoffeeBreakBean bean component updates the values in the shopping cart, which are then redisplayed by orderForm. When the order is complete, the customer proceeds to the checkoutForm page by clicking the Checkout button.

The table of coffees displayed on the orderForm is rendered using one of the JavaServer Faces component tags, dataTable. Here is part of the dataTable tag from orderForm:

<h:dataTable id="table"
    columnClasses="list-column-center,list-column-right,
        list-column-center, list-column-right"
    headerClass="list-header" rowClasses="list-row"
    footerClass="list-column-right"
    styleClass="list-background-grid"
    value="#{CoffeeBreakBean.cart.items}" var="sci">
    <f:facet name="header">
        <h:outputText  value="#{CBMessages.OrderForm}"/>
    </f:facet>
    <h:column>
        <f:facet name="header">
            <h:outputText  value="Coffee"/>
        </f:facet>
        <h:outputText id="coffeeName"
            value="#{sci.item.coffeeName}"/>
    </h:column>
    ...
</h:dataTable>

When this tag is processed, a UIData component and a Table renderer are created on the server side. The UIData component supports a data binding to a collection of data objects. The Table renderer takes care of generating the HTML markup. The UIData component iterates through the list of coffees, and the Table renderer renders each row in the table.

This example is a classic use case for a UIData component because the number of coffees might not be known to the application developer or the page author at the time the application is developed. Also, the UIData component can dynamically adjust the number of rows in the table to accommodate the underlying data.

For more information on UIData, please see Using Data-Bound Table Components.

The checkoutForm Page

checkoutForm is used to collect delivery and billing information from the customer. When the Submit button is clicked, an ActionEvent is generated. This event is first handled by the submit method of the checkoutFormBean. This method acts as a listener for the event because the tag corresponding to the submit button references the submit method with its action attribute:

<h:commandButton value="#{CBMessages.Submit}"
    action="#{checkoutFormBean.submit}"/>

The submit method submits the suborders to each supplier and stores the result in the request-scoped OrderConfirmations bean.

The checkoutForm page has standard validators on several components and a custom validator on the email component. Here is the tag corresponding to the firstName component, which holds the customer’s first name:

<h:inputText id="firstName" value="#{checkoutFormBean.firstName}"
    size="15" maxlength="20" required="true"/>

With the required attribute set to true, the JavaServer Faces implementation will check whether the user entered something in the First Name field.

The email component has a custom validator registered on it. Here is the tag corresponding to the email component:

<h:inputText id="email" value="#{checkoutFormBean.email}"
    size="25" maxlength="125" validator="#{checkoutFormBean.validateEmail}"/>

The validator attribute refers to the validateEmail method on the CheckoutFormBean class. This method ensures that the value the user enters in the email field contains an @ character.

If the validation does not succeed, the checkoutForm is re-rendered, with error notifications in each invalid field. If the validation succeeds, checkoutFormBean submits suborders to each supplier and stores the result in the request-scoped OrderConfirmations JavaBeans component and control is passed to the checkoutAck page.

The checkoutAck Page

checkoutAck simply displays the contents of the OrderConfirmations JavaBeans component, which is a list of the suborders constituting an order and the ship dates of each suborder. This page also uses a UIData component. Again, the number of coffees the customer ordered is not known before runtime. The UIData component dynamically adds rows to accommodate the order.

The checkoutAck.jsp page also makes use of a custom converter that converts the shipping date into an XMLGregorianCalendar type:

<h:outputText id="coffeeName"
    value="#{oc.confirmationBean.shippingDate}">
    <f:converter converterId="XMLGregorianCalendarConverter" /
</h:outputText>

The custom converter is implemented by XMLGregorianCalendarConverter.java.