Walkthrough of CarStore JSF Sample...

Post on 24-Sep-2020

4 views 0 download

Transcript of Walkthrough of CarStore JSF Sample...

1

1

Walkthrough ofCarStore JSF Sample

Application

In our previous class, we have gone though a simple JSF application called guessNumber.

In this presentation, we will walk through a more complex JSF application, carstore, which also comes with J2EE 1.4 SDK.

04/29/2004

2

2

Sang Shin

sang.shin@sun.comwww.javapassion.com

Java™ Technology EvangelistSun Microsystems, Inc.

04/29/2004

3

3

Disclaimer & Acknowledgments? Even though Sang Shin is a full-time employee of Sun

Microsystems, the contents here is created as his own personal endeavor and thus does not reflect any official stance of Sun Microsystems.

? Sun Microsystems is not responsible for any inaccuracies in the contents.

? Acknowledgments: – Many slides and speaker notes are created from JSF tutorial– Source code examples are from sample codes that are shipped with JSF

beta

04/29/2004

4

4

Revision History? 12/28/2003: version 1: created by Sang Shin? 04/03/2004: version 2: updated with JSF version 1.0 that

comes with J2EE 1.4 SDK ? Things to do

– speaker notes need to be polished a bit

04/29/2004

5

5

CarStoreSample Application

04/29/2004

6

6

Sample JSP Application we are going to build? CarStore application that comes with

J2EE 1.4 SDK– <install>/samples/jsf/carstore– Windows: C:\Sun\AppServer1\samples\jsf\carstore

? Simulates online car dealership– select a locale– select a car model– add options– get an updated price– buy the car

The carstore application simulates a simple online car dealership through which a user can select a locale, select a car model, add options, and then get updated price, and finally buy the car.

04/29/2004

7

7

Page Flow

Here's a quick diagram of page flow through the application. Each box corresponds to a JSP page. The arrows correspond to the supported flow from page to page, either with buttons in the page, or with the browser navigation buttons.

04/29/2004

8

8

Backing Beans (Model Objects)

We then overlay the beans required to back the JSP pages. These beans are called backing beans. In MVC pattern, they correspond to model objects.

04/29/2004

9

9

Beans

Data

Finally, we add the back end data. In this simple application, the data is read from java.util.ResourceBundle instances, but it could just as well come from a database.

04/29/2004

10

10

Page Flow of CarStore Application

So let' go over the page flow of carstore application.

04/29/2004

11

11

JSP Pages used for End UserPresentation? chooseLocale.jsp? storeFront.jsp? carDetail.jsp? confirmChoices.jsp? finish.jsp? customerInfo.jsp

This slide shows the list of JSP pages in the carstore application. In the following slides, we will go over each of this pages and how they are presented in the browser.

04/29/2004

12

12

JSP Pages Included in OtherJSP Pages? optionsPanel.jsp

– included in carDetails.jsp? bottomMatter.jsp

– footer page– included in carDetails.jsp, chooseLocale.jsp,

confirmChoices.jsp, finish.jsp, storeFront.jsp

The carstore application also has two JSP pages which are included in the other JSP pages. The optionsPanel.jsp is included in the carDetails.jsp while the bottomMatter.jsp is included in the bottom of all the displayed JSP pages.

04/29/2004

13

13

chooseLocale.jsp

The chooseLocale.jsp page is the first page that gets displayed and allows you to select a locale.

04/29/2004

14

14

chooseLocale.jsp (page 1)

1 <html>2 <head>3 <title>CarStore</title>4 <link rel="stylesheet" type="text/css"5 href='<%= request.getContextPath() + "/stylesheet.css" %>'>6 </head>7 8 <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>9 <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>10 <%@ taglib uri="http://java.sun.com/jsf/demo/components" prefix="d" %>11 12 <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/>

This is the first part of the chooseLocale.jsp page. Here we see the declaration of JSF tag libraries, html and core. Since this application also has its own custom tag library called components, it also needs to be declared.

Please also note the <f:loadBundle> element through which a resource bundle is specified. The value of the “var” attribute, “bundle”, in this example, is used as a prefix when any localized message is refered to in this page.

04/29/2004

15

15

chooseLocale.jsp (page 2)

1 <f:view>2 <h:form>3 4 <h:panelGrid columns="1" 5 footerClass="form-footer"6 headerClass="form-header"7 styleClass="main-background"8 columnClasses="single-column"9 summary="#{bundle.chooseLocale}" 10 title="#{bundle.chooseLocale}" >11 12 <h:graphicImage url="/images/cardemo.jpg" /> 13 14 <h:outputText styleClass="maintitle"15 value="#{bundle.chooseLocale}" />16 17 <h:graphicImage id="mapImage" url="/images/world.jpg" 18 alt="#{bundle.chooseLocale}"19 usemap="#worldMap" />

This is the continuation of the chooseLocale.jsp. Here we are using <h:panelGrid> to have a table format. (This might not be obvious since things are displayed in graphics.)

The first <h:graphicImage> displays the carstore.jpg on the top. The <h:outputText> then display the main title. Then the <h:graphicImage> is used to display the world map.

04/29/2004

16

16

chooseLocale.jsp (page 3)

1 <d:map id="worldMap" current="NAmericas" immediate="true"2 action="storeFront"3 actionListener="#{carstore.chooseLocaleFromMap}">4 <d:area id="NAmerica" value="#{NA}" 5 onmouseover="/images/world_namer.jpg" 6 onmouseout="/images/world.jpg" 7 targetImage="mapImage" />8 <d:area id="SAmerica" value="#{SA}" 9 onmouseover="/images/world_samer.jpg"10 onmouseout="/images/world.jpg" 11 targetImage="mapImage" />12 <d:area id="Germany" value="#{gerA}" 13 onmouseover="/images/world_germany.jpg" 14 onmouseout="/images/world.jpg" 15 targetImage="mapImage" />16 <d:area id="France" value="#{fraA}" 17 onmouseover="/images/world_france.jpg" 18 onmouseout="/images/world.jpg" 19 targetImage="mapImage" />20 </d:map>21

Here we are using custom UI component called <d:map> in which 4 different world image files are refered to depending on which locale a user selected.

04/29/2004

17

17

chooseLocale.jsp (page 4) 1 <h:form>2 <!-- For non graphical browsers -->3 <h:panelGrid id="links" columns="4" 4 summary="#{bundle.chooseLocale}" 5 title="#{bundle.chooseLocale}" >6 <h:commandLink id="NAmerica" action="storeFront"7 actionListener="#{carstore.chooseLocaleFromLink}">8 <h:outputText value="#{bundle.english}" />9 </h:commandLink>10 <h:commandLink id="Germany" action="storeFront"11 actionListener="#{carstore.chooseLocaleFromLink}">12 <h:outputText value="#{bundle.german}" />13 </h:commandLink>14 <h:commandLink id="France" action="storeFront"15 actionListener="#{carstore.chooseLocaleFromLink}">16 <h:outputText value="#{bundle.french}" />17 </h:commandLink>18 <h:commandLink id="SAmerica" action="storeFront"19 actionListener="#{carstore.chooseLocaleFromLink}">20 <h:outputText value="#{bundle.spanish}" />21 </h:commandLink>22 </h:panelGrid> 23 </h:form>

This is the continuation of chooseLocale.jsp. The elements in this slide are used for non-graphical browsers.

04/29/2004

18

18

storeFront.jsp

This is how storeFront.jsp page is displayed. Now let's see the contents of the storeFront.jsp from the next slide.

04/29/2004

19

19

storeFront.jsp (page 1)

1 <HTML>2 3 <HEAD>4 <TITLE>Welcome to CarStore</TITLE>5 <link rel="stylesheet" type="text/css"6 href='<%= request.getContextPath() + "/stylesheet.css" %>'>7 </HEAD>8 <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>9 <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>10 11 <BODY BGCOLOR="white">12 13 <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/>

This is the first part of the storeFront.jsp. Since this part is the common for all the the JSP pages, I will move on. I included it here for the sake of completeness.

04/29/2004

20

20

storeFront.jsp (page 2)

1 <f:view> 2 <h:form>3 <h:graphicImage url="/images/cardemo.jpg" /> 4 <h:panelGrid columns="2" 5 footerClass="form-footer"6 headerClass="form-header"7 styleClass="top-table"8 columnClasses="single-column"9 summary="#{bundle.chooseCar}" 10 title="#{bundle.chooseCar}" >11 12 <h:panelGrid columns="2"13 styleClass="storeFrontCar">14 ...next page...15 </h:panelGrid>16 <h:panelGrid columns="2"17 styleClass="storeFrontCar">18 ...19 </h:panelGrid>20 </h:panelGrid>21 </h:form>

column 1 column 2

This is the continuation of the storeFront.jsp page. Here we are using nested <h:panelGrid> elements. The outmost <h:panelGrid> element has two columns as illustrated in the picture on the right side of the slide. The inside <h:panelGrid> element also has two columns which we will see in the following slide.

04/29/2004

21

21

storeFront.jsp (page 3)

<h:panelGrid columns="2" styleClass="storeFrontCar"> <!-- Jalopy --> <h:graphicImage binding="#{carstore.models.Jalopy.components.imageSmall}" /> <h:outputText styleClass="subtitlebig" value="#{carstore.models.Jalopy.attributes.title}" /> <h:outputText value="#{carstore.models.Jalopy.attributes.description}"/> <h:commandButton action="#{carstore.storeFrontJalopyPressed}"

10 value="#{bundle.moreButton}" >11 </h:commandButton>12 <!-- Roadster -->13 <h:graphicImage binding="#{carstore.models.Roadster.components.imageSmall}" />14 <h:outputText styleClass="subtitlebig"15 value="#{carstore.models.Roadster.attributes.title}" />16 <h:outputText 17 value="#{carstore.models.Roadster.attributes.description}" /> 18 <h:commandButton 19 action="#{carstore.storeFrontRoadsterPressed}" 20 value="#{bundle.moreButton}" >21 </h:commandButton>22 </h:panelGrid>

This slide shows the contents of the inside <h:grid_panel> elements of the previous slide. Here 8 UI components are displayed in two columns. Please see the UI component and its corresponding display by following through the arrows.

04/29/2004

22

22

carDetails.jsp (upper)

Now once a user selects a car mode, the carDetails.jsp page gets displayed . This page allows you to choose the options for a particular car model. Since this page is too long to display in a single slide, I divided it into two slides. This slide shows the upper part of the page while the next slide shows the lower part of the page.

04/29/2004

23

23

carDetails.jsp (lower)

This slide shows the lower part of the carDetails.jsp page. Now let's go over the actual contents of the carDetails.jsp page from the following slide.

04/29/2004

24

24

carDetails.jsp (page 1)

1 <f:view>2 <h:form>3 4 <!-- non-option details -->5 <h:panelGrid columns="1"6 summary="#{bundle.carDetails}"7 title="#{bundle.carDetails}">8 9 <h:graphicImage url="/images/cardemo.jpg" /> 10 11 <h:graphicImage 12 binding="#{carstore.currentModel.components.image}" />13 14 <h:outputText styleClass="subtitlebig"15 binding="#{carstore.currentModel.components.title}" />16 17 <h:outputText 18 binding="#{carstore.currentModel.components.description}" />

This part of the carDetails.jsp page shows the header, car model image, car model's title, and car model description. Please note JSF EL expression “#{carstore.currentModel.components.title}”.

The “carstore” is the main bean for the carstore application. It maintains a Map of CarBean instances, keyed by model name, and a Map of CarCustomizer instances, keyed by package name. The “currentModel” property of the “carstore” bean contains the CarBean instance of the selected car model. A CarBean instance contains a Map of UI components.

04/29/2004

25

25

carDetails.jsp (page 2)

1 <h:panelGrid columns="2">2 3 <h:outputText styleClass="subtitle"4 value="#{bundle.basePriceLabel}" />5 6 <h:outputText 7 binding="#{carstore.currentModel.components.basePrice}" />8 9 <h:outputText styleClass="subtitle"10 value="#{bundle.yourPriceLabel}" />11 12 <h:outputText value="#{carstore.currentModel.currentPrice}" />13 14 </h:panelGrid>15 16 <h:commandButton action="#{carstore.buyCurrentCar}"17 value="#{bundle.buy}" />18 19 </h:panelGrid>

This is continuation of carDetails.jsp page. Here “Best Price” label and the corresponding value of the selected car model and “Your Price” label and the corresponding value of the selected car model are displayed in a table form.

04/29/2004

26

26

carDetails.jsp (page 3)

1 <jsp:include page="optionsPanel.jsp"/>2 3 <h:commandButton value="#{bundle.recalculate}" 4 action="#{carstore.currentModel.updatePricing}" 5 immediate="true" />6 7 <h:commandButton action="#{carstore.buyCurrentCar}"8 value="#{bundle.buy}" />9 10 </h:form>11 12 <jsp:include page="bottomMatter.jsp"/>13 14 </f:view>

The carDetails.jsp page includes optionsPanel.jsp. The things that are displayed by optionsPanel.jsp page is inside the box on the right side of the slide.

The "Recalculate" and "Buy" buttons are then displayed.

04/29/2004

27

27

optionsPanel.jsp (page 1)

1 <!--2 Copyright 2003 Sun Microsystems, Inc. All rights reserved.3 SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.4 -->5 <%@ page contentType="text/html" language="java" %>6 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>7 <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>8 <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>9 10 <f:subview id="optionsPanel">11 12 <h:panelGrid>13 14 <h:outputText value="#{bundle.OptionsPackages}" />

This slide shows the beginning part of the contents of the optionsPanel.jsp. Please note the <f:subview> element. If you want to include a JavaServer Faces page within another JavaServer Faces page or another JSP page, you must enclose the entire nested page in a <f:subview> tag.

04/29/2004

28

28

optionsPanel.jsp (page 2)

1 <h:panelGrid columns="4"> 2 3 <h:commandButton id="Custom" value="#{bundle.Custom}" immediate="true"4 styleClass="#{carstore.customizers.Custom.buttonStyle}"5 actionListener="#{carstore.choosePackage}" />6 7 <h:commandButton id="Standard" value="#{bundle.Standard}" immediate="true"8 styleClass="#{carstore.customizers.Standard.buttonStyle}"9 actionListener="#{carstore.choosePackage}" />10 11 <h:commandButton id="Performance" value="#{bundle.Performance}" immediate="true"12 styleClass="#{carstore.customizers.Performance.buttonStyle}"13 actionListener="#{carstore.choosePackage}" />14 15 <h:commandButton id="Deluxe" value="#{bundle.Deluxe}" immediate="true"16 styleClass="#{carstore.customizers.Deluxe.buttonStyle}"17 actionListener="#{carstore.choosePackage}" />18 19 </h:panelGrid>

This is the continuation of optionsPanel.jsp page. Here the four packaging options - Custom, Standard, Performance, and Deluxe - are displayed via <h:commandButton> elements.

04/29/2004

29

29

optionsPanel.jsp (page 3)

1 <h:panelGrid columns="2">2 3 <h:outputText value="#{bundle.Engine}" 4 styleClass="optionLabel"/>5 6 <h:selectOneMenu styleClass="optionValue"7 binding="#{carstore.currentModel.components.engine}"/>8 9 <h:outputText value="#{bundle.Brakes}" 10 styleClass="optionLabel" />11 12 <h:selectone_radio styleClass="optionValue"13 binding="#{carstore.currentModel.components.brake}"/>14 ...

This is continuation of the optionsPanel.jsp page. Here Engine and Brake selections are displayed as top down menu and radio button selection.

04/29/2004

30

30

optionsPanel.jsp (page 4)

1 <h:outputText value="#{bundle.OtherOptions}" 2 styleClass="optionLabel"/>3 4 <h:panelGrid columns="6">5 6 <h:selectboolean_checkbox title="#{bundle.sunroofLabel}" 7 alt="#{bundle.sunroofLabel}" 8 binding="#{carstore.currentModel.components.sunroof}">9 </h:selectboolean_checkbox> 10 <h:outputText value="#{bundle.sunroofLabel}" /> 11 12 <h:selectboolean_checkbox title="#{bundle.cruiseLabel}" 13 binding="#{carstore.currentModel.components.cruisecontrol}" >14 </h:selectboolean_checkbox>15 <h:outputText value="#{bundle.cruiseLabel}" /> 16 . .17 <h:selectboolean_checkbox title="#{bundle.towPkgLabel}" 18 alt="#{bundle.towPkgLabel}" 19 binding="#{carstore.currentModel.components.towPackage}" >20 </h:selectboolean_checkbox>21 <h:outputText value="#{bundle.towPkgLabel}" /> 22 . .

This is the continuation of the optionsPanel.jsp page. Here other options can be selected as a table which has 6 columns. The odd columns display the checkbox for each option and even columns display the labels of the options.

04/29/2004

31

31

confirmChoices.jsp

This slide shows the options currently chosen for a particular car model.

04/29/2004

32

32

confirmChoices.jsp (page 1)

1 <f:view> 2 <h:form>3 4 <h:panelGrid id="mainPanel" columns="1" footerClass="subtitle"5 styleClass="medium" columnClasses="medium">6 7 <h:graphicImage url="/images/cardemo.jpg" />8 <h:outputText binding="#{carstore.currentModel.components.title}" />

This is the beginning part of the confirmChoices.jsp page. There cardemo.jpg and the title of a car model gets displayed first.

04/29/2004

33

33

confirmChoices.jsp (page 2)

1 <h:panelGrid columns="2" footerClass="subtitle"2 headerClass="subtitlebig" styleClass="medium" columnClasses="subtitle,medium">3 4 <f:facet name="header">5 <h:outputText value="#{bundle.buyTitle}" />6 </f:facet>7 8 <h:outputText value="#{bundle.Engine}" />9 <h:outputText value="#{carstore.currentModel.attributes.engine}" />10 11 <h:outputText value="#{bundle.Brakes}" />12 <h:outputText value="#{carstore.currentModel.attributes.brake}" />13 14 ...

This is continuation of the confirmChoices.jsp page. Here we are displaying a table which has two columns. The first column displays the localized text of each option and the second column displays the value chosen by the buyer.

04/29/2004

34

34

confirmChoices.jsp (page 3)

1 <h:panelGroup>2 <h:commandButton value="#{bundle.buy}" action="customerInfo" 3 title="#{bundle.buy}" />4 <h:commandButton value="#{bundle.back}" action="carDetail" 5 title="#{bundle.back}"/>6 </h:panelGroup>7 8 </h:panelGrid>9 </h:form>10 <jsp:include page="bottomMatter.jsp"/>11 </f:view>

This slide shows the “Buy” and “Back” buttons.

04/29/2004

35

35

customerInfo.jsp

This slide shows how customerInfo.jsp gets displayed so that customer information such as name and address can be entered by the buyer.

04/29/2004

36

36

customerInfo.jsp (page 1)

1 <h:form >2 3 <h:panelGrid id="mainPanel" columns="1" footerClass="subtitle"4 headerClass="subtitlebig" styleClass="medium" columnClasses="medium">5 6 <h:graphicImage url="/images/cardemo.jpg" />7 8 <h:outputText value="#{bundle.customerTitle}" />

This is the beginning part of the customerInfo.jsp page. Here the cardemo.jpg and customerTitle text get displayed first.

04/29/2004

37

37

customerInfo.jsp (page 2)

1 <h:panelGrid id="subPanel" columns="3" footerClass="medium"2 headerClass="subtitlebig" styleClass="medium" columnClasses="medium">3 4 <h:outputText value="#{bundle.titleLabel}" />5 <h:selectOneMenu id="title" value="#{customer.currentTitle}">6 <f:selectItems value="#{customer.titleOptions}" />7 </h:selectOneMenu>8 <h:outputText value=""/>

This is the continuation of the customerInfo.jsp page.

04/29/2004

38

38

customerInfo.jsp (page 3)

1 <h:outputText value="#{bundle.firstLabel}" />2 <h:inputText id="firstName" value="#{customer.firstName}" required="true"> 3 <f:valueChangeListener type="carstore.FirstNameChanged" />4 </h:inputText>5 <h:messages styleClass="validationMessage" for="firstName"/>6 7 <h:outputText value="#{bundle.middleLabel}" />8 <h:inputText id="middleInitial" size="1" maxlength="1" 9 value="#{customer.middleInitial}" > 10 </h:inputText>11 <h:messages styleClass="validationMessage" for="middleInitial"/>

T

04/29/2004

39

39

customerInfo.jsp (page 4)

1 <h:outputText value="#{bundle.lastLabel}" />2 <h:inputText value="#{customer.lastName}" />3 <h:outputText value=""/>4 5 <h:outputText value="#{bundle.mailingLabel}"/>6 <h:inputText value="#{customer.mailingAddress}" />7 <h:outputText value=""/>8 9 <h:outputText value="#{bundle.cityLabel}" />10 <h:inputText value="#{customer.city}" />11 <h:outputText value=""/>

T

04/29/2004

40

40

customerInfo.jsp (page 5) 1 <h:outputText value="#{bundle.stateLabel}" />2 <h:selectOneMenu value="#{customer.state}" >3 4 <f:selectItem itemValue="AL" itemLabel="AL" />5 <f:selectItem itemValue="AK" itemLabel="AK"/>6 <f:selectItem itemValue="AZ" itemLabel="AZ"/>7 <f:selectItem itemValue="AR" itemLabel="AR"/>8 <f:selectItem itemValue="CA" itemLabel="CA"/>9 ...10 </h:selectOneMenu>11 <h:outputText value=""/>

T

04/29/2004

41

41

customerInfo.jsp (page 6) 1 <h:outputText value="#{bundle.zipLabel}" />2 <h:inputText id="zip" 3 value="#{customer.zip}"4 size="10" required="true">5 <cs:format_validator formatPatterns="99999|99999-9999|### ###"/> 6 </h:inputText>7 <h:messages styleClass="validationMessage" for="zip" />

T

04/29/2004

42

42

customerInfo.jsp (page 7) 1 <h:outputText value="#{bundle.ccNumberLabel}" />2 <h:inputText id="ccno" size="16"3 converter="#{creditCardConverter}" required="true">4 <cs:format_validator 5 formatPatterns="9999999999999999|9999 9999 9999 9999|9999-9999-9999-9999"/>6 </h:inputText>7 <h:messages styleClass="validationMessage" for="ccno"/>

T

04/29/2004

43

43

customerInfo.jsp (page 8) 1 <h:outputText value="#{bundle.monthLabel}" />2 3 <h:panelGrid id="monthYearPanel" columns="2" footerClass="medium"4 headerClass="medium" styleClass="medium" columnClasses="medium">5 6 <h:selectOneMenu value="#{customer.month}">7 <f:selectItem itemValue="01" itemLabel="01"/>8 <f:selectItem itemValue="02" itemLabel="02"/>9 ...10 <f:selectItem itemValue="11" itemLabel="11"/>11 <f:selectItem itemValue="12" itemLabel="12"/>12 </h:selectOneMenu>13 <h:selectOneMenu value="#{customer.year}" >14 <f:selectItem itemValue="2002" itemLabel="2002"/>15 <f:selectItem itemValue="2003" itemLabel="2003"/>16 ...17 <f:selectItem itemValue="2008" itemLabel="2008"/>18 </h:selectOneMenu>19 20 </h:panelGrid>21 22 <h:outputText value=""/>

T

04/29/2004

44

44

customerInfo.jsp (page 9) 1 <h:commandButton value="#{bundle.finishButton}" action="finish" />2 <h:graphicImage id="duke" url="/images/duke.gif" />3 <h:outputText value="#{bundle.buyLabel}" />4 5 </h:panelGrid>6 </h:form>7 </f:view>

T

04/29/2004

45

45

finish.jsp

The final page that thanks you for ordering the car

04/29/2004

46

46

finish.jsp (page 1) 1 <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/>2 <f:view> 3 <h:form>4 <h:graphicImage url="/images/cardemo.jpg" />5 6 <h:panelGrid id="thanksPanel" columns="1" footerClass="subtitle"7 headerClass="subtitlebig" styleClass="medium" columnClasses="subtitle,medium">8 <f:facet name="header">9 <h:outputMessage value="#{bundle.thanksLabel}">10 <f:parameter value="#{sessionScope.firstName}"/>11 </h:outputMessage>12 </f:facet>13 </h:panelGrid>14 15 </h:form>16 <jsp:include page="bottomMatter.jsp"/>17 </f:view>

This is the finish.jsp page. Please note the first name is inserted as a parameter to #{bundle.thanksLabel} message.

04/29/2004

47

47

Backing Beans

04/29/2004

48

48

Beans (repeat)

The beans we will look into are colored in blue. There are three beans: CarStore bean, CarBean, and CustomerBean.

04/29/2004

49

49

Backing Beans? CarStore bean

– Main bean for the application– Maintains a map of CarBean instances, keyed by

model name– Maintains a map of CarCustomizer instances,

keyed by package name? CarBean bean

– Encapsulates a car model, including pricing and package choices

? CustomerBean bean– Represents a customer

The CarStore bean is the main bean for this application. It maintains a map of CarBean instances keyed by model name. It also maintains a map of CarCustomer instances keyed by package name.

The CarBean bean encaptulates a car model including pricing and package options.

The CustomerBean bean represents the customer.

04/29/2004

50

50

CarStore Bean (page 1)

? Several pages in the application use this bean as the target of method reference and value reference expressions.

– "chooseLocale.jsp" page uses actionListener attributes to point to the chooseLocaleFromMap(javax.faces.event.ActionEvent) and chooseLocaleFromLink(javax.faces.event.ActionEvent) methods.

– "storeFront.jsp" page uses value binding expressions to pull information about four of the known car models in the store.

(read slide)

04/29/2004

51

51

CarStore Bean (page 2)

? Several pages in the application use this bean as the target of method reference and value reference expressions.

– "carDetail" page uses value binding expressions to pull information about the currently chosen model. It also uses the action attribute to convey the user's package choices.

– "confirmChoices" page uses value binding expressions to pull the user's choices from the currently chosen model.

(read slide)

04/29/2004

52

52

chooseLocale.jsp

1 <d:map id="worldMap" current="NAmericas" immediate="true"2 action="storeFront"3 actionListener="#{carstore.chooseLocaleFromMap}">4 <d:area id="NAmerica" value="#{NA}" 5 onmouseover="/images/world_namer.jpg" 6 onmouseout="/images/world.jpg" 7 targetImage="mapImage" />8 <d:area id="SAmerica" value="#{SA}" 9 onmouseover="/images/world_samer.jpg"10 onmouseout="/images/world.jpg" 11 targetImage="mapImage" />12 <d:area id="Germany" value="#{gerA}" 13 onmouseover="/images/world_germany.jpg" 14 onmouseout="/images/world.jpg" 15 targetImage="mapImage" />16 <d:area id="France" value="#{fraA}" 17 onmouseover="/images/world_france.jpg" 18 onmouseout="/images/world.jpg" 19 targetImage="mapImage" />20 </d:map>21

So you have seen this part of chooseLocale.jsp page. Here you see the actionListener attribute of <d:map> element is set to chooseLocaleFromMap() method of the carstore bean. (It is highlighted in blue color.) When a user selects a locale by pressing one of the 4 areas, an action event is generated and the chooseLocaleFromMap() method gets called.

04/29/2004

53

53

catStore.java 1 public class CarStore extends Object {2 ...3 public void chooseLocaleFromMap(ActionEvent actionEvent) {4 AreaSelectedEvent event = (AreaSelectedEvent) actionEvent;5 String current = event.getMapComponent().getCurrent();6 FacesContext context = FacesContext.getCurrentInstance();7 context.getViewRoot().setLocale((Locale) locales.get(current));8 resetMaps();9 } 10 ...11 private void resetMaps() {12 if (null != carModels) {13 carModels.clear();14 carModels = null;15 }16 if (null != carCustomizers) {17 carCustomizers.clear();18 carCustomizers = null;19 }20 }

This slide shows the chooseLocaleFromMap() method of the carstore bean. It first casts the ActionEvent type to AreaSelectedEvent type. From the event, it gets UI component that generates the event – getMapComponent() method. It then gets information on what the current selection is – getCurrent() method. It then saves it in the context object.

04/29/2004

54

54

storeFront.jsp

<h:panelGrid columns="2" styleClass="storeFrontCar"> <!-- Jalopy --> <h:graphicImage binding="#{carstore.models.Jalopy.components.imageSmall}" /> <h:outputText styleClass="subtitlebig" value=" #{carstore.models.Jalopy.attributes.title} " /> <h:outputText value=" #{carstore.models.Jalopy.attributes.description}"/> <h:commandButton action=" #{carstore.storeFrontJalopyPressed} "

10 value="#{bundle.moreButton}" >11 </h:commandButton>12 <!-- Roadster -->13 <h:graphicImage binding="#{carstore.models.Roadster.components.imageSmall} " />14 <h:outputText styleClass="subtitlebig"15 value=" #{carstore.models.Roadster.attributes.title}" />16 <h:outputText 17 value=" #{carstore.models.Roadster.attributes.description} " /> 18 <h:commandButton 19 action=" #{carstore.storeFrontRoadsterPressed}" 20 value="#{bundle.moreButton}" >21 </h:commandButton>22 </h:panelGrid>

This part of storeFront.jsp page shows value bindings of outputText component and action binding of the commandButton component. And the values of value and action binding attributes refers to carstore bean.

Note that the “carstore.models” will result in calling getModels() method of the carstore bean as we will see in the next slide.

04/29/2004

55

55

catStore.java 1 public class CarStore extends Object {2 ...3 // Car models we offer. Key=name of package, Value=CarBean instances4 private Map carModels = null;5 public Map getModels() {6 if (null == carModels) {7 carModels = new HashMap();8 if (log.isDebugEnabled()) {9 log.debug("Populating carModel map");10 }11 carModels.put(DEFAULT_MODEL, 12 new CarBean(DEFAULT_MODEL_PROPERTIES));13 carModels.put("Roadster", 14 new CarBean(CARSTORE_PREFIX + ".bundles.Roadster"));15 carModels.put("Luxury", new CarBean(CARSTORE_PREFIX + 16 ".bundles.Luxury"));17 carModels.put("SUV", new CarBean(CARSTORE_PREFIX + 18 ".bundles.SUV"));19 }20 return carModels;21 }

This is the getModels() method of the carStore bean. In this mode, a map object in which model sring values such as “Roadster”, “Luxury”, or “SUV” are used as keys and CarBean object is saved as values.

04/29/2004

56

56

carDetails.jsp (page 1)

1 <f:view>2 <h:form>3 4 <!-- non-option details -->5 <h:panelGrid columns="1"6 summary="#{bundle.carDetails}"7 title="#{bundle.carDetails}">8 9 <h:graphicImage url="/images/cardemo.jpg" /> 10 11 <h:graphicImage 12 binding="#{carstore.currentModel.components.image}" />13 14 <h:outputText styleClass="subtitlebig"15 binding="#{carstore.currentModel.components.title}" />16 17 <h:outputText 18 binding="#{carstore.currentModel.components.description}" />

This is carDetailes.jsp page in which currentModel field of the carstore bean is referenced. Again, we expect to see getCurrentModel() method in the carstore bean.

04/29/2004

57

57

carDetails.jsp (page 2)

1 <h:panelGrid columns="2">2 3 <h:outputText styleClass="subtitle"4 value="#{bundle.basePriceLabel}" />5 6 <h:outputText 7 binding="#{carstore.currentModel.components.basePrice}" />8 9 <h:outputText styleClass="subtitle"10 value="#{bundle.yourPriceLabel}" />11 12 <h:outputText value="#{carstore.currentModel.currentPrice}" />13 14 </h:panelGrid>15 16 <h:commandButton action="#{carstore.buyCurrentCar}"17 value="#{bundle.buy}" />18 19 </h:panelGrid>

This is the continuation of the carDetails.jsp page. Here we see action attribute of <h:commandButton> also refer to buyCurrentCar() method of the carstore bean.

04/29/2004

58

58

carDetails.jsp (page 3)

1 <jsp:include page="optionsPanel.jsp"/>2 3 <h:commandButton value="#{bundle.recalculate}" 4 action="#{carstore.currentModel.updatePricing}" 5 immediate="true" />6 7 <h:commandButton action="#{carstore.buyCurrentCar}"8 value="#{bundle.buy}" />9 10 </h:form>11 12 <jsp:include page="bottomMatter.jsp"/>13 14 </f:view>

This is the continuation of carDetails.jsp page.

04/29/2004

59

59

CarStore.java 1 public class CarStore extends Object {2 ...3 4 5 public String buyCurrentCar() {6 getCurrentModel().getCurrentPrice();7 return "confirmChoices";8 } 9 10 public CarBean getCurrentModel() {11 CarBean result = (CarBean) carModels.get(getCurrentModelName());12 return result;13 }14 15 ...16 }

This slide shows the two methods mentioned in the previous slides. The buyCurrentCar() method is a action listener method while the getCurrentModel() is an accessor method of a property field of the Carstore bean.

04/29/2004

60

60

CarBean

? Encapsulates a car model, including pricing and package choices

? The system allows the user to customize the properties of this bean with the help of the CarCustomizer

? Only bean in the application that has access to the persistent store of data

– In the present implementation, this persistent store is in ResourceBundle instances

(read the slide)

04/29/2004

61

61

components & attributes in CarBean

1 public class CarBean extends Object {2 ...3 /**4 * Keys: String attribute name, such as engine. Values: UIComponent5 * for the attribute6 */7 private Map components = null;8 ...9 public Map getAttributes() {10 return attributes;11 }12 ...13 /**14 * Keys: String attribute name, such as engine. Values: String value15 * of the component named by key in our components Map.16 */17 private Map attributes = null;18 ...19 public Map getAttributes() {20 return attributes;21 }22 ...

Where key is the name of an attribute of this car. For example, basePrice, or description. key_componentType is the component type of the UIComponent subclass to be used to represent this attribute in the page, for example SelectManyMenu. key_valueType is the data type of the value of the UIComponent, for example java.lang.Integer. For all non-String valueTypes.

When the bean is instantiated, we load both of the above properties files and iterate over the keys in each one. For each key, we look at the componentType and ask the Application to create a component of that type. We store that UIComponent instance in our components Map under the name key. We look at the valueType for the key. For non java.lang.String types, we ask the Application for a Converter instance for that class. If found, we use it to convert the value for the key to the appropriate type and store that as the value of the UIComponent instance.

04/29/2004

62

62

Where CarBean is Referenced?? chooseLocale.jsp

– uses actionListener attributes to point to the chooseLocaleFromMap(ActionEvent) and chooseLocaleFromLink(ActionEvent) methods

? storeFront.jsp – uses value binding expressions to pull information

about four of the known car models in the store

Several pages in the application use this bean as the target of method reference and value reference expressions.

04/29/2004

63

63

Where CarBean is Referenced?

? carDetail.jsp– uses value binding expressions to pull information

about the currently chosen model – also uses the action attribute to convey the user's

package choices? confirmChoices.jsp

– uses value binding expressions to pull the user's choices from the currently chosen model

(read the slide)

04/29/2004

64

64

Reference of CarBean instance in carDetails.jsp

1 <jsp:include page="optionsPanel.jsp"/>2 3 <h:commandButton value="#{bundle.recalculate}" 4 action="#{carstore.currentModel .updatePricing}" 5 immediate="true" />6 7 <h:commandButton action="#{carstore.buyCurrentCar}"8 value="#{bundle.buy}" />9 10 </h:form>11 12 <jsp:include page="bottomMatter.jsp"/>13 14 </f:view>

The circled part of carDetails.jsp page shows how updatePricing() method of the CarBean instance will get invoked when a buyer clicks the “Recalculate” botton. Typically an action method should return an outcome so that navigation handler can select a next page to display. However, as you will see in the next slide, the updatePricing() method returns null. It is because the goal of this action method is to recalculate the price and the same page needs to be displayed but with updated price. (Sang: I need to find out why action listener tag is not used in this case.)

04/29/2004

65

65

updatePricing() method in CarBean

1 public class CarBean extends Object {2 ...3 public String updatePricing() {4 getCurrentPrice();5 return null;6 }7 8 public Integer getCurrentPrice() {9 // go through our options and try to get the prices10 int sum = ((Integer)((ValueHolder)getComponents().get("basePrice")).11 getValue()).intValue();12 Iterator iter = getComponents().keySet().iterator();13 String key = null;14 Object value = null;15 UIComponent component = null;16 while (iter.hasNext()) {17 key = (String) iter.next();18 component = (UIComponent) getComponents().get(key);19 value = ((ValueHolder)component).getValue();20 if (null == value || (!(component instanceof UIInput))) {21 continue;22 }23

The cod above shows the updatePricing() method in the CarBean that is invoked as an action method as shown in the previous slide.

The getCurrentPrice() method that is invoked inside updatePricing()method does the following:(1) get the base price of the car(2) go through the iterator of options and for each option, get the price of it and add it to the base price of the car(3) the result will be saved as “currentPrice”

This currentPrice will be displayed next time carDetails.jsp page is displayed.

04/29/2004

66

66

Reference to CarBean in confirmChoices.jsp

1 <h:panelGrid columns="2" footerClass="subtitle"2 headerClass="subtitlebig" styleClass="medium" columnClasses="subtitle,medium">3 4 <f:facet name="header">5 <h:outputText value="#{bundle.buyTitle}" />6 </f:facet>7 8 <h:outputText value="#{bundle.Engine}" />9 <h:outputText value="#{carstore.currentModel.attributes.engine}" />10 11 <h:outputText value="#{bundle.Brakes}" />12 <h:outputText value=" #{carstore.currentModel.attributes.brake}" />13 14 ...

This is continuation of the confirmChoices.jsp page. Here we are displaying a table which has two columns. The first column displays the localized text of each option and the second column displays the value chosen by the buyer.

04/29/2004

67

67

Supporting Class to Backing Beans

? CarCustomizer.java– Customizes a CarBean for a set of options in an

options package

The CarCustomizer class is not a backing bean itself but a supporting class. It is used to customize a CarBean for a set of options in a option package.

04/29/2004

68

68

Bundles asData Source

04/29/2004

69

69

Beans

Data (repeat)

Finally, we add the back end data. In this simple application, the data is read from java.util.ResourceBundle instances, but it could just as well come from a database.

04/29/2004

70

70

Data Source Resource Bundles

? <ModelName>.properties– Contains the localized content for this model– There is a variant of this file for each supported locale,

for example, Jalopy_de.properties? Common_options.properties

– Contains the localized content common to all models? <ModelName_options>

– Contains the non-localized content for this model, including the non-localized options

– There is only one variant of this file for all locales for example, Jalopy_options.properties

In this application, this persistent store is in the form of ResourceBundle instances.

There are three data source ResourceBundle files used:

1.<ModelName>:This contains the localized content for this model. There is a variant of this file for each supported locale, for example, Jalopy_de.properties

2.<Common_properties>: This contains the localized content common to all models.

3.<ModelName_options>:This contains the non-localized content for this model, including the non-localized options. There is only one variant of this file for all locales for example, Jalopy_options.properties

04/29/2004

71

71

Key Convention

? Convention– key– key_componentType– key_valueType

D

04/29/2004

72

72

Bundles

? Common_options.properties? Custom.properties? Deluxe.properties? Jalopy.properties, Jalopy_de.properties,

Jalopy_es.properties, Jalopy_fr.properties? ...

D

04/29/2004

73

73

Bundles

? Common_options.properties? Custom.properties? Deluxe.properties? Jalopy.properties, Jalopy_de.properties,

Jalopy_es.properties, Jalopy_fr.properties? ...

D

04/29/2004

74

74

Common_options.properties

1 # this file contains the non-localized set of options common to all cars2 3 sunroof=false4 sunroof_componentType=SelectBooleanCheckbox5 sunroof_valueType=java.lang.Boolean6 cruisecontrol=false7 cruisecontrol_componentType=SelectBooleanCheckbox8 cruisecontrol_valueType=java.lang.Boolean9 keylessentry=false10 keylessentry_componentType=SelectBooleanCheckbox11 keylessentry_valueType=java.lang.Boolean12 securitySystem=false13 securitySystem_componentType=SelectBooleanCheckbox14 securitySystem_valueType=java.lang.Boolean15 skiRack=false16 skiRack_componentType=SelectBooleanCheckbox17 skiRack_valueType=java.lang.Boolean18 towPackage=false19 towPackage_componentType=SelectBooleanCheckbox20 towPackage_valueType=java.lang.Boolean21 gps=false22 gps_componentType=SelectBooleanCheckbox23 gps_valueType=java.lang.Boolean

T

04/29/2004

75

75

Custom.properties

1 # false represents unselected, true represents selected2 # other values represent the currently selected option3 sunroof=false4 sunroof_disabled=false5 cruisecontrol=false6 cruisecontrol_disabled=false7 keylessentry=false8 keylessentry_disabled=false9 securitySystem=false10 securitySystem_disabled=false11 skirack=false12 skirack_disabled=false13 towPackage=false14 towPackage_disabled=false15 gps=false16 gps_disabled=false17 18 engine=V419 brake=Disc20 suspension=Regular21 speaker=422 audio=Standard23 transmission=Manual

T

04/29/2004

76

76

Deluxe.properties

1 # false represents unselected, true represents selected2 # other values represent the currently selected option3 sunroof=true4 sunroof_disabled=false5 cruisecontrol=true6 cruisecontrol_disabled=false7 keylessentry=true8 keylessentry_disabled=false9 securitySystem=true10 securitySystem_disabled=false11 skirack=true12 skirack_disabled=false13 towPackage=true14 towPackage_disabled=false15 gps=true16 gps_disabled=false17 18 engine=V819 brake=Drum20 suspension=Regular21 speaker=622 audio=Premium23 transmission=Auto

T

04/29/2004

77

77

Jalopy.properties

1 # this file contains the localized content for the Jalopy 2 3 title=Duke's Stripped-Down Jalopy4 title_componentType=OutputText5 title_valueType=java.lang.String6 description=If you're the type who doesn't care what anyone thinks, this 7 is the car for you. Strictly for point-a-to-point-b types.8 description_componentType=OutputText9 description_valueType=java.lang.String

T

04/29/2004

78

78

Jalopy_de.properties

1 # this file contains the localized content for the Jalopy 2 3 title=Dukes alte Kiste4 title_componentType=OutputText5 title_valueType=java.lang.String6 description=Wenn Sie der Typ von Mensch sind, den es nicht k\u00fcmmert, 7 was jeder denkt, dann ist dies genau der richtige Wagen 8 f\u00fcr Sie! Gedacht f\u00fcr Punkt-A-Nach-Punkt-B Typen. 9 description_componentType=OutputText10 description_valueType=java.lang.String

T

04/29/2004

79

79

Event Handler

04/29/2004

80

80

Event Handler

? FirstNameChanged class– ValueChangeListener type– Handles the event of entering a value in the First

Name field on the customerInfo.jsp page? LocaleChanged class

– ActionListener type– Handles the event of a user selecting a locale

D

04/29/2004

81

81

ProcessValueChange() method in FirstNameChanged.Java

1 public class FirstNameChanged extends Object implements ValueChangeListener {2 3 public void processValueChange (ValueChangeEvent event)4 throws AbortProcessingException {5 if (null != event.getNewValue()) {6 FacesContext.getCurrentInstance().7 getExternalContext().8 getSessionMap().9 put("firstName", event.getNewValue());10 }11 }12 13 public PhaseId getPhaseId() {14 return PhaseId.ANY_PHASE;15 }16 17 }18

This is FirstNameChanged class which implements ValueChangeListener interface.

The processValueChange() method of the listener stores the first name that the user enters into session scope map. When the finish page is loaded, this first name information will be retrieved and inserted inside the message, "Thanks {0} for using cardemo. Your car will ship soon."

04/29/2004

82

82

Example: customerInfo.jsp (CarStore)

<h:inputText id="firstName" value="#{customer.firstName}" required="true"> <f:valueChangeListener type="carstore.FirstNameChanged" /></h:inputText>

The FirstNameChanged listener implementation is registered on the firstName UIInput component on the customerInfo.jsp page.

04/29/2004

83

83

Example: LocaleChange Listener(CarStore) ...public class LocaleChange extends Object implements ActionListener {

public void processAction(ActionEvent event) throws AbortProcessingException { String current = event.getComponent().getId(); FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale((Locale) locales.get(current)); resetMaps(); } }

The carstore application does not use any ActionListener implementations. Instead, it uses actionListener expressions that point to bean methods that handle events. This section explains how to turn one of these methods into an ActionListener implementation.

The chooseLocale page allows the user to select a locale for the application by clicking on one of a set of hyperlinks. When the user clicks one of the hyperlinks, an ActionEvent is generated, and the chooseLocaleFromLink(ActionEvent) method of the CarStore bean is invoked. Instead of implementing a bean method to handle this event, you can create a listener implementation to handle it. To do this, you need to:

* Move the chooseLocaleFromLink(ActionEvent) method to a class that implements ActionListener * Rename the method to processAction(ActionEvent)

The listener implementation would look something like above.

04/29/2004

84

84

Example: chooseLocale.jsp if it uses <f:actionListener> <h:commandLink id="NAmerica" action="storeFront"> <f:actionListener type="carstore.LocaleChange" /></h:commandLink>

Here is one of the commandLink tags on the chooseLocale page, changed to reference an ActionListener implementation rather than a bean method:

04/29/2004

85

85

Validator

04/29/2004

86

86

Validator

? FormatValidator.java– Defines a custom Validator

D

04/29/2004

87

87

Example: Custom validator used for zip code in customerInfo.jsp (CarStore)

T

04/29/2004

88

88

Example: validate() method of FormatValidator (CarStore)–page1

public void validate(FacesContext context, UIInput component) { boolean valid = false; String value = null; if ((context == null) || (component == null)) { throw new NullPointerException(); } if (!(component instanceof UIOutput)) { return; } if ( formatPatternsList == null ) { component.setValid(true); return; }

This method gets the local value of the component and converts it to a String. It then iterates over the formatPatternsList list, which is the list of acceptable patterns as specified in the formatPatterns attribute of the format_validator tag.

04/29/2004

89

89

Example: validate() method of FormatValidator (CarStore)-page2

Object input = ((UIOutput)component).getValue(); if(input != null) { value = input.toString(); //validate the value against the list of valid patterns. Iterator patternIt = formatPatternsList.iterator(); while (patternIt.hasNext()) { valid = isFormatValid( ((String)patternIt.next()), value); if (valid) { break; } }

While iterating over the list, this method checks the pattern of the local value against the patterns in the list. If the pattern of the local value does not match any pattern in the list, this method: marks the component's local value invalid by calling component.setValid(false), generates an error message, and queues the error message to the FacesContext so that the message is displayed on the page during the Render Response phase.

04/29/2004

90

90

Example: validate() method of FormatValidator (CarStore)-page3

if ( valid ) { component.setValid(true); } else { component.setValid(false); FacesMessage errMsg = MessageFactory.getMessage(context, FORMAT_INVALID_MESSAGE_ID, (new Object[] {formatPatterns})); context.addMessage(component.getClientId(context)), errMsg); } }}

The error messages are retrieved from the Application instance by MessageFactory. An application that creates its own custom messages must provide a class, like MessageFactory, that retrieves the messages from the Application instance. When creating your own application, you can simply copy the MessageFactory class from the cardemo application to your application.

The getMessage method of MessageFactory takes a FacesContext, a static String that represents the key into the Properties file, and the format pattern as an Object. The key corresponds to the static message ID in the FormatValidator class:

public static final String FORMAT_INVALID_MESSAGE_ID = "cardemo.Format_Invalid";}

When the error message is displayed, the format pattern will be substituted for the {0} in the error message, which, in English, is:

Input must match one of the following patterns {0}

04/29/2004

91

91

Example: Registering Error Messages through App. Conf. File (CarStore)

<application> <message-bundle>carstore.bundles.Messages</message-bundle> <locale-config> <default-locale>en</default-locale> <supported-locale>de</supported-locale> <supported-locale>fr</supported-locale> <supported-locale>es</supported-locale> </locale-config></application>

Here is the part of the file that registers the error messages for the cardemo application:

04/29/2004

92

92

faces-config.xml 1 <!-- Validator -->2 <validator>3 <description>4 Registers the concrete Validator implementation,5 carstore.FormatValidator with the validator6 identifier, FormatValidator.7 </description>8 <validator-id>FormatValidator</validator-id>9 <validator-class>carstore.FormatValidator</validator-class>10 <attribute>11 <description>12 List of format patterns separated by '|'. The validator13 compares these patterns against the data entered in a 14 component that has this validator registered on it.15 </description>16 <attribute-name>formatPatterns</attribute-name>17 <attribute-class>java.lang.String</attribute-class>18 </attribute>19 </validator>

T

04/29/2004

93

93

Converter

04/29/2004

94

94

Converter

? CreditCardConverter.java– Accepts a Credit Card Number of type String and

strips blanks and "-" if any from it

D

04/29/2004

95

95

CreditCardConverter in CarStore

Sometimes you might want to convert a component's data to a type other than a standard type, or you might want to convert the format of the data. To facilitate this, JavaServer Faces technology allows you to register a Converter implementation on UIOutput components and components whose classes subclass UIOutput.

04/29/2004

96

96

Example: getAsString() in CreditCardConverter (CarStore)

public String getAsString(FacesContext context, UIComponent component,Object value) throws ConverterException { String inputVal = null; if ( value == null ) { return null; } try { inputVal = (String)value; } catch (ClassCastException ce) { throw new ConverterException(Util.getExceptionMessage( Util.CONVERSION_ERROR_MESSAGE_ID)); } char[] input = inputVal.toCharArray(); StringBuffer buffer = new StringBuffer(50); for ( int i = 0; i < input.length; ++i ) { if ( (i % 4) == 0 && i != 0) { if (input[i] != ' ' || input[i] != '-'){ buffer.append(" "); } else if (input[i] == '-') { buffer.append(" "); } } buffer.append(input[i]);

Here is the implementation of getAsString() method from CreditCardConverter class.

04/29/2004

97

97

faces-config.xml 1 <!-- converter -->2 <converter>3 <description>4 Registers the concrete Converter implementation,5 carstore.CreditCardConverter using the ID, 6 creditcard.7 </description>8 <converter-id>creditcard</converter-id>9 <converter-class>carstore.CreditCardConverter</converter-class>10 </converter>

T

04/29/2004

98

98

Custom Components &Renderer

04/29/2004

99

99

Custom Component

? AreaComponent.java– The class that defines the component

corresponding to the area custom tag

D

04/29/2004

100

100

Renderer

? AreaRenderer.java– This Renderer performs the delegated rendering

for the UIArea component

D

04/29/2004

101

101

Custom Tag Files,TLD files

04/29/2004

102

102

Custom Tag Classes

? AreaTag– tag handler that implements the area custom tag

? ImageArea– bean that stores the shape and coordinates of the

hot spots? MapComponent

– class that defines the component orresponding to the map custom tag

? MapTag– tag handler that implements the map custom tag

D

04/29/2004

103

103

TLD file

? carstore.tld– Defines carstore.FormatValidatorTag

D

04/29/2004

104

104

Stylesheet

04/29/2004

105

105

Stylesheet

? stylesheet.css

D

04/29/2004

106

106

storeFront.jsp (page 1)

1 <HTML>2 3 <HEAD>4 <TITLE>Welcome to CarStore</TITLE>5 <link rel="stylesheet" type="text/css"6 href='<%= request.getContextPath() + "/stylesheet.css" %>'>7 </HEAD>8 <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>9 <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>10 11 <BODY BGCOLOR="white">12 13 <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/>

This is the first part of the storeFront.jsp. Since this part is the common for all the the JSP pages, I will move on. I included it here for the sake of completeness.

04/29/2004

107

107

storeFront.jsp (page 2)

1 <f:view> 2 <h:form>3 <h:graphicImage url="/images/cardemo.jpg" /> 4 <h:panelGrid columns="2" 5 footerClass="form-footer"6 headerClass="form-header"7 styleClass="top-table"8 columnClasses="single-column"9 summary="#{bundle.chooseCar}" 10 title="#{bundle.chooseCar}" >11 12 <h:panelGrid columns="2"13 styleClass="storeFrontCar">14 ...15 </h:panelGrid>16 <h:panelGrid columns="2"17 styleClass="storeFrontCar">18 ...19 </h:panelGrid>20 </h:panelGrid>21 </h:form>

column 1 column 2

T

04/29/2004

108

108

stylesheet.css (page 1)

1 ...2 .top-table { 3 padding: 0;4 border: 0;5 width: 660px;6 }7 8 .storeFrontCar { 9 padding: 010 border: 011 }12 ...

This is the first part of the storeFront.jsp. Since this part is the common for all the the JSP pages, I will move on. I included it here for the sake of completeness.

04/29/2004

109

109

catStore.java 1 public class CarStore extends Object {2 ...3 public void choosePackage(String packageName) {4 CarCustomizer packageCustomizer = (CarCustomizer) carCustomizers.get(packageName);5 packageCustomizer.customizeCar(getCurrentModel());6 getCurrentModel().getCurrentPrice();7 8 // HERE IS WHERE WE UPDATE THE BUTTON STYLE!9 String curName;10 Iterator iter = carCustomizers.keySet().iterator();11 // go through all the available packages and set the button style accordingly.12 while (iter.hasNext()) {13 curName = (String) iter.next();14 packageCustomizer = (CarCustomizer) carCustomizers.get(curName);15 if (curName.equals(packageName)) {16 packageCustomizer.setButtonStyle("package-selected");17 }18 else {19 packageCustomizer.setButtonStyle("package-unselected");20 }21 }22 }23 ...24 }

T

04/29/2004

110

110

stylesheet.css (page 2)

1 ...2 .package-selected {3 background-color: #93B629;4 }5 6 .package-unselected {7 background-color: #C0C0C0;8 }9 ...

This is the first part of the storeFront.jsp. Since this part is the common for all the the JSP pages, I will move on. I included it here for the sake of completeness.

04/29/2004

111

111

Configuration Files

04/29/2004

112

112

faces-config.xml 1

2 <faces-config>3 <application>...</application>4 <validator>...</validator>5 <converter>...</converter>6 <managed-bean>...</managed-bean>7 ...8 <managed-bean>...</managed-bean>9 <navigation-rule>...</navigation-rule>10 ...11 <navigation-rule>...</navigation-rule>12 </faces-config>

T

04/29/2004

113

113

faces-config.xml (page2) 1 <application>2 <message-bundle>carstore.bundles.Messages</message-bundle>3 <locale-config>4 <default-locale>en</default-locale>5 <supported-locale>de</supported-locale>6 <supported-locale>fr</supported-locale>7 <supported-locale>es</supported-locale>8 </locale-config>9 </application>

T

04/29/2004

114

114

Images

04/29/2004

115

115

?

D

04/29/2004

116

116

? duke.gif

D

04/29/2004

117

117

?

D

04/29/2004

118

118

?

D

04/29/2004

119

119

Passion!

04/29/2004