Walkthrough of CarStore JSF Sample Application
Transcription
Walkthrough of CarStore JSF Sample Application
04/29/2004 Walkthrough of CarStore JSF Sample Application 1 04/29/2004 Sang Shin [email protected] www.javapassion.com Java ™ Technology Evangelist Sun Microsystems, Inc. 2 04/29/2004 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 3 04/29/2004 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 4 04/29/2004 CarStore Sample Application 5 04/29/2004 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 6 04/29/2004 Page Flow 7 04/29/2004 Backing Beans (Model Objects) 8 04/29/2004 Data Beans 9 04/29/2004 Page Flow of CarStore Application 10 04/29/2004 JSP Pages used for End User Presentation ? ? ? ? ? ? chooseLocale.jsp storeFront.jsp carDetail.jsp confirmChoices.jsp finish.jsp customerInfo.jsp 11 04/29/2004 JSP Pages Included in Other JSP Pages ? optionsPanel.jsp – ? included in carDetails.jsp bottomMatter.jsp – – footer page included in carDetails.jsp, chooseLocale.jsp, confirmChoices.jsp, finish.jsp, storeFront.jsp 12 04/29/2004 chooseLocale.jsp 13 04/29/2004 chooseLocale.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 <html> <head> <title>CarStore</title> <link rel="stylesheet" type="text/css" href='<%= request.getContextPath() + "/stylesheet.css" %>'> </head> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/demo/components" prefix="d" %> <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/> 14 04/29/2004 chooseLocale.jsp (page 2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <f:view> <h:form> <h:panelGrid columns="1" footerClass="form-footer" headerClass="form-header" styleClass="main-background" columnClasses="single-column" summary="#{bundle.chooseLocale}" title="#{bundle.chooseLocale}" > <h:graphicImage url="/images/cardemo.jpg" /> <h:outputText styleClass="maintitle" value="#{bundle.chooseLocale}" /> <h:graphicImage id="mapImage" url="/images/world.jpg" alt="#{bundle.chooseLocale}" usemap="#worldMap" /> 15 04/29/2004 chooseLocale.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <d:map id="worldMap" current="NAmericas" immediate="true" action="storeFront" actionListener="#{carstore.chooseLocaleFromMap}"> <d:area id="NAmerica" value="#{NA}" onmouseover="/images/world_namer.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="SAmerica" value="#{SA}" onmouseover="/images/world_samer.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="Germany" value="#{gerA}" onmouseover="/images/world_germany.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="France" value="#{fraA}" onmouseover="/images/world_france.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> </d:map> 16 04/29/2004 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> 17 04/29/2004 storeFront.jsp 18 04/29/2004 storeFront.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 13 <HTML> <HEAD> <TITLE>Welcome to CarStore</TITLE> <link rel="stylesheet" type="text/css" href='<%= request.getContextPath() + "/stylesheet.css" %>'> </HEAD> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <BODY BGCOLOR="white"> <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/> 19 04/29/2004 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" column 1 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 2 20 04/29/2004 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}" value="#{bundle.moreButton}" > </h:commandButton> <!-- Roadster --> <h:graphicImage binding="#{carstore.models.Roadster.components.imageSmall}" /> <h:outputText styleClass="subtitlebig" value="#{carstore.models.Roadster.attributes.title}" /> <h:outputText value="#{carstore.models.Roadster.attributes.description}" /> <h:commandButton action="#{carstore.storeFrontRoadsterPressed}" value="#{bundle.moreButton}" > </h:commandButton> </h:panelGrid> 21 04/29/2004 carDetails.jsp (upper) 22 04/29/2004 carDetails.jsp (lower) 23 04/29/2004 carDetails.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <f:view> <h:form> <!-- non-option details --> <h:panelGrid columns="1" summary="#{bundle.carDetails}" title="#{bundle.carDetails}"> <h:graphicImage url="/images/cardemo.jpg" /> <h:graphicImage binding="#{carstore.currentModel.components.image}" /> <h:outputText styleClass="subtitlebig" binding="#{carstore.currentModel.components.title}" /> <h:outputText binding="#{carstore.currentModel.components.description}" /> 24 04/29/2004 carDetails.jsp (page 2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <h:panelGrid columns="2"> <h:outputText styleClass="subtitle" value="#{bundle.basePriceLabel}" /> <h:outputText binding="#{carstore.currentModel.components.basePrice}" /> <h:outputText styleClass="subtitle" value="#{bundle.yourPriceLabel}" /> <h:outputText value="#{carstore.currentModel.currentPrice}" /> </h:panelGrid> <h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" /> </h:panelGrid> 25 04/29/2004 carDetails.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <jsp:include page="optionsPanel.jsp"/> <h:commandButton value="#{bundle.recalculate}" action="#{carstore.currentModel.updatePricing}" immediate="true" /> <h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" /> </h:form> <jsp:include page="bottomMatter.jsp"/> </f:view> 26 04/29/2004 optionsPanel.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <!-Copyright 2003 Sun Microsystems, Inc. All rights reserved. SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. --> <%@ page contentType="text/html" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <f:subview id="optionsPanel"> <h:panelGrid> <h:outputText value="#{bundle.OptionsPackages}" /> 27 04/29/2004 optionsPanel.jsp (page 2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <h:panelGrid columns="4"> <h:commandButton id="Custom" value="#{bundle.Custom}" immediate="true" styleClass="#{carstore.customizers.Custom.buttonStyle}" actionListener="#{carstore.choosePackage}" /> <h:commandButton id="Standard" value="#{bundle.Standard}" immediate="true" styleClass="#{carstore.customizers.Standard.buttonStyle}" actionListener="#{carstore.choosePackage}" /> <h:commandButton id="Performance" value="#{bundle.Performance}" immediate="true" styleClass="#{carstore.customizers.Performance.buttonStyle}" actionListener="#{carstore.choosePackage}" /> <h:commandButton id="Deluxe" value="#{bundle.Deluxe}" immediate="true" styleClass="#{carstore.customizers.Deluxe.buttonStyle}" actionListener="#{carstore.choosePackage}" /> </h:panelGrid> 28 04/29/2004 optionsPanel.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <h:panelGrid columns="2"> <h:outputText value="#{bundle.Engine}" styleClass="optionLabel"/> <h:selectOneMenu styleClass="optionValue" binding="#{carstore.currentModel.components.engine}"/> <h:outputText value="#{bundle.Brakes}" styleClass="optionLabel" /> <h:selectone_radio styleClass="optionValue" binding="#{carstore.currentModel.components.brake}"/> ... 29 0 1 2 3 4 5 6 7 8 9 0 1 2 04/29/2004 optionsPanel.jsp (page 4) <h:outputText value="#{bundle.OtherOptions}" styleClass="optionLabel"/> <h:panelGrid columns="6"> <h:selectboolean_checkbox title="#{bundle.sunroofLabel}" alt="#{bundle.sunroofLabel}" binding="#{carstore.currentModel.components.sunroof}"> </h:selectboolean_checkbox> <h:outputText value="#{bundle.sunroofLabel}" /> <h:selectboolean_checkbox title="#{bundle.cruiseLabel}" binding="#{carstore.currentModel.components.cruisecontrol}" > </h:selectboolean_checkbox> <h:outputText value="#{bundle.cruiseLabel}" /> .. <h:selectboolean_checkbox title="#{bundle.towPkgLabel}" alt="#{bundle.towPkgLabel}" binding="#{carstore.currentModel.components.towPackage}" > </h:selectboolean_checkbox> <h:outputText value="#{bundle.towPkgLabel}" /> .. 30 04/29/2004 confirmChoices.jsp 31 04/29/2004 confirmChoices.jsp (page 1) 1 2 3 4 5 6 7 8 <f:view> <h:form> <h:panelGrid id="mainPanel" columns="1" footerClass="subtitle" styleClass="medium" columnClasses="medium"> <h:graphicImage url="/images/cardemo.jpg" /> <h:outputText binding="#{carstore.currentModel.components.title}" /> 32 04/29/2004 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 ... 33 04/29/2004 confirmChoices.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 <h:panelGroup> <h:commandButton value="#{bundle.buy}" action="customerInfo" title="#{bundle.buy}" /> <h:commandButton value="#{bundle.back}" action="carDetail" title="#{bundle.back}"/> </h:panelGroup> </h:panelGrid> </h:form> <jsp:include page="bottomMatter.jsp"/> </f:view> 34 04/29/2004 customerInfo.jsp 35 04/29/2004 customerInfo.jsp (page 1) 1 2 3 4 5 6 7 8 <h:form > <h:panelGrid id="mainPanel" columns="1" footerClass="subtitle" headerClass="subtitlebig" styleClass="medium" columnClasses="medium"> <h:graphicImage url="/images/cardemo.jpg" /> <h:outputText value="#{bundle.customerTitle}" /> 36 04/29/2004 customerInfo.jsp (page 2) 1 2 3 4 5 6 7 8 <h:panelGrid id="subPanel" columns="3" footerClass="medium" headerClass="subtitlebig" styleClass="medium" columnClasses="medium"> <h:outputText value="#{bundle.titleLabel}" /> <h:selectOneMenu id="title" value="#{customer.currentTitle}"> <f:selectItems value="#{customer.titleOptions}" /> </h:selectOneMenu> <h:outputText value=""/> 37 04/29/2004 customerInfo.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 <h:outputText value="#{bundle.firstLabel}" /> <h:inputText id="firstName" value="#{customer.firstName}" required="true"> <f:valueChangeListener type="carstore.FirstNameChanged" /> </h:inputText> <h:messages styleClass="validationMessage" for="firstName"/> <h:outputText value="#{bundle.middleLabel}" /> <h:inputText id="middleInitial" size="1" maxlength="1" value="#{customer.middleInitial}" > </h:inputText> <h:messages styleClass="validationMessage" for="middleInitial"/> 38 04/29/2004 customerInfo.jsp (page 4) 1 2 3 4 5 6 7 8 9 10 11 <h:outputText value="#{bundle.lastLabel}" /> <h:inputText value="#{customer.lastName}" /> <h:outputText value=""/> <h:outputText value="#{bundle.mailingLabel}"/> <h:inputText value="#{customer.mailingAddress}" /> <h:outputText value=""/> <h:outputText value="#{bundle.cityLabel}" /> <h:inputText value="#{customer.city}" /> <h:outputText value=""/> 39 04/29/2004 customerInfo.jsp (page 5) 1 2 3 4 5 6 7 8 9 10 11 <h:outputText value="#{bundle.stateLabel}" /> <h:selectOneMenu value="#{customer.state}" > <f:selectItem itemValue="AL" itemLabel="AL" /> <f:selectItem itemValue="AK" itemLabel="AK"/> <f:selectItem itemValue="AZ" itemLabel="AZ"/> <f:selectItem itemValue="AR" itemLabel="AR"/> <f:selectItem itemValue="CA" itemLabel="CA"/> ... </h:selectOneMenu> <h:outputText value=""/> 40 04/29/2004 customerInfo.jsp (page 6) 1 2 3 4 5 6 7 <h:outputText value="#{bundle.zipLabel}" /> <h:inputText id="zip" value="#{customer.zip}" size="10" required="true"> <cs:format_validator formatPatterns="99999|99999-9999|### ###"/> </h:inputText> <h:messages styleClass="validationMessage" for="zip" /> 41 04/29/2004 customerInfo.jsp (page 7) 1 2 3 4 5 6 7 <h:outputText value="#{bundle.ccNumberLabel}" /> <h:inputText id="ccno" size="16" converter="#{creditCardConverter}" required="true"> <cs:format_validator formatPatterns="9999999999999999|9999 9999 9999 9999|9999-9999-9999-9999 </h:inputText> <h:messages styleClass="validationMessage" for="ccno"/> 42 0 1 2 3 4 5 6 7 8 9 0 1 2 04/29/2004 customerInfo.jsp (page 8) <h:outputText value="#{bundle.monthLabel}" /> <h:panelGrid id="monthYearPanel" columns="2" footerClass="medium" headerClass="medium" styleClass="medium" columnClasses="medium"> <h:selectOneMenu value="#{customer.month}"> <f:selectItem itemValue="01" itemLabel="01"/> <f:selectItem itemValue="02" itemLabel="02"/> ... <f:selectItem itemValue="11" itemLabel="11"/> <f:selectItem itemValue="12" itemLabel="12"/> </h:selectOneMenu> <h:selectOneMenu value="#{customer.year}" > <f:selectItem itemValue="2002" itemLabel="2002"/> <f:selectItem itemValue="2003" itemLabel="2003"/> ... <f:selectItem itemValue="2008" itemLabel="2008"/> </h:selectOneMenu> </h:panelGrid> <h:outputText value=""/> 43 04/29/2004 customerInfo.jsp (page 9) 1 2 3 4 5 6 7 <h:commandButton value="#{bundle.finishButton}" action="finish" /> <h:graphicImage id="duke" url="/images/duke.gif" /> <h:outputText value="#{bundle.buyLabel}" /> </h:panelGrid> </h:form> </f:view> 44 04/29/2004 finish.jsp 45 04/29/2004 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,med 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> 46 04/29/2004 Backing Beans 47 04/29/2004 Beans (repeat) 48 04/29/2004 Backing Beans ? CarStore bean – – – ? CarBean 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 Encapsulates a car model, including pricing and package choices CustomerBean bean – Represents a customer 49 04/29/2004 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. 50 04/29/2004 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. 51 04/29/2004 chooseLocale.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <d:map id="worldMap" current="NAmericas" immediate="true" action="storeFront" actionListener="#{carstore.chooseLocaleFromMap}"> <d:area id="NAmerica" value="#{NA}" onmouseover="/images/world_namer.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="SAmerica" value="#{SA}" onmouseover="/images/world_samer.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="Germany" value="#{gerA}" onmouseover="/images/world_germany.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> <d:area id="France" value="#{fraA}" onmouseover="/images/world_france.jpg" onmouseout="/images/world.jpg" targetImage="mapImage" /> </d:map> 52 04/29/2004 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 } 53 04/29/2004 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}" value="#{bundle.moreButton}" > </h:commandButton> <!-- Roadster --> <h:graphicImage binding="#{carstore.models.Roadster.components.imageSmall}" /> <h:outputText styleClass="subtitlebig" value="#{carstore.models.Roadster.attributes.title}" /> <h:outputText value="#{carstore.models.Roadster.attributes.description}" /> <h:commandButton action="#{carstore.storeFrontRoadsterPressed}" value="#{bundle.moreButton}" > </h:commandButton> </h:panelGrid> 54 04/29/2004 catStore.java 1 public class CarStore extends Object { 2 ... 3 // Car models we offer. Key=name of package, Value=CarBean instances 4 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 } 55 04/29/2004 carDetails.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <f:view> <h:form> <!-- non-option details --> <h:panelGrid columns="1" summary="#{bundle.carDetails}" title="#{bundle.carDetails}"> <h:graphicImage url="/images/cardemo.jpg" /> <h:graphicImage binding="#{carstore.currentModel.components.image}" /> <h:outputText styleClass="subtitlebig" binding="#{carstore.currentModel.components.title}" /> <h:outputText binding="#{carstore.currentModel.components.description}" /> 56 04/29/2004 carDetails.jsp (page 2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <h:panelGrid columns="2"> <h:outputText styleClass="subtitle" value="#{bundle.basePriceLabel}" /> <h:outputText binding="#{carstore.currentModel.components.basePrice}" /> <h:outputText styleClass="subtitle" value="#{bundle.yourPriceLabel}" /> <h:outputText value="#{carstore.currentModel.currentPrice}" /> </h:panelGrid> <h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" /> </h:panelGrid> 57 04/29/2004 carDetails.jsp (page 3) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <jsp:include page="optionsPanel.jsp"/> <h:commandButton value="#{bundle.recalculate}" action="#{carstore.currentModel.updatePricing}" immediate="true" /> <h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" /> </h:form> <jsp:include page="bottomMatter.jsp"/> </f:view> 58 04/29/2004 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 } 59 04/29/2004 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 60 04/29/2004 components & attributes in CarBean 1 public class CarBean extends Object { 2 ... 3 /** 4 * Keys: String attribute name, such as engine. Values: UIComponent 5 * for the attribute 6 */ 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 value 15 * 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 ... 61 04/29/2004 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 62 04/29/2004 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 63 04/29/2004 Reference of CarBean instance in carDetails.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <jsp:include page="optionsPanel.jsp"/> <h:commandButton value="#{bundle.recalculate}" action="#{carstore.currentModel.updatePricing}" immediate="true" /> <h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" /> </h:form> <jsp:include page="bottomMatter.jsp"/> </f:view> 64 04/29/2004 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 prices 10 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 65 04/29/2004 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 ... 66 04/29/2004 Supporting Class to Backing Beans ? CarCustomizer.java – Customizes a CarBean for a set of options in an options package 67 04/29/2004 Bundles as Data Source 68 04/29/2004 Data (repeat) Beans 69 04/29/2004 Data Source Resource Bundles ? <ModelName>.properties – – ? Common_options.properties – ? Contains the localized content for this model There is a variant of this file for each supported locale, for example, Jalopy_de.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 70 04/29/2004 Key Convention ? Convention – – – key key_componentType key_valueType 71 04/29/2004 Bundles ? ? ? ? ? Common_options.properties Custom.properties Deluxe.properties Jalopy.properties, Jalopy_de.properties, Jalopy_es.properties, Jalopy_fr.properties ... 72 04/29/2004 Bundles ? ? ? ? ? Common_options.properties Custom.properties Deluxe.properties Jalopy.properties, Jalopy_de.properties, Jalopy_es.properties, Jalopy_fr.properties ... 73 04/29/2004 Common_options.properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # this file contains the non-localized set of options common to all cars sunroof=false sunroof_componentType=SelectBooleanCheckbox sunroof_valueType=java.lang.Boolean cruisecontrol=false cruisecontrol_componentType=SelectBooleanCheckbox cruisecontrol_valueType=java.lang.Boolean keylessentry=false keylessentry_componentType=SelectBooleanCheckbox keylessentry_valueType=java.lang.Boolean securitySystem=false securitySystem_componentType=SelectBooleanCheckbox securitySystem_valueType=java.lang.Boolean skiRack=false skiRack_componentType=SelectBooleanCheckbox skiRack_valueType=java.lang.Boolean towPackage=false towPackage_componentType=SelectBooleanCheckbox towPackage_valueType=java.lang.Boolean gps=false gps_componentType=SelectBooleanCheckbox gps_valueType=java.lang.Boolean 74 04/29/2004 Custom.properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # false represents unselected, true represents selected # other values represent the currently selected option sunroof=false sunroof_disabled=false cruisecontrol=false cruisecontrol_disabled=false keylessentry=false keylessentry_disabled=false securitySystem=false securitySystem_disabled=false skirack=false skirack_disabled=false towPackage=false towPackage_disabled=false gps=false gps_disabled=false engine=V4 brake=Disc suspension=Regular speaker=4 audio=Standard transmission=Manual 75 04/29/2004 Deluxe.properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # false represents unselected, true represents selected # other values represent the currently selected option sunroof=true sunroof_disabled=false cruisecontrol=true cruisecontrol_disabled=false keylessentry=true keylessentry_disabled=false securitySystem=true securitySystem_disabled=false skirack=true skirack_disabled=false towPackage=true towPackage_disabled=false gps=true gps_disabled=false engine=V8 brake=Drum suspension=Regular speaker=6 audio=Premium transmission=Auto 76 04/29/2004 Jalopy.properties 1 2 3 4 5 6 7 8 9 # this file contains the localized content for the Jalopy title=Duke's Stripped-Down Jalopy title_componentType=OutputText title_valueType=java.lang.String description=If you're the type who doesn't care what anyone thinks, this is the car for you. Strictly for point-a-to-point-b types. description_componentType=OutputText description_valueType=java.lang.String 77 04/29/2004 Jalopy_de.properties 1 2 3 4 5 6 7 8 9 10 # this file contains the localized content for the Jalopy title=Dukes alte Kiste title_componentType=OutputText title_valueType=java.lang.String description=Wenn Sie der Typ von Mensch sind, den es nicht k\u00fcmmert, was jeder denkt, dann ist dies genau der richtige Wagen f\u00fcr Sie! Gedacht f\u00fcr Punkt-A-Nach-Punkt-B Typen. description_componentType=OutputText description_valueType=java.lang.String 78 04/29/2004 Event Handler 79 04/29/2004 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 80 04/29/2004 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 81 04/29/2004 Example: customerInfo.jsp (CarStore) <h:inputText id="firstName" value="#{customer.firstName}" required="true"> <f:valueChangeListener type="carstore.FirstNameChanged" /> </h:inputText> 82 04/29/2004 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(); } } 83 04/29/2004 Example: chooseLocale.jsp if it uses <f:actionListener> <h:commandLink id="NAmerica" action="storeFront"> <f:actionListener type="carstore.LocaleChange" /> </h:commandLink> 84 04/29/2004 Validator 85 04/29/2004 Validator ? FormatValidator.java – Defines a custom Validator 86 04/29/2004 Example: Custom validator used for zip code in customerInfo.jsp (CarStore) 87 04/29/2004 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; } 88 04/29/2004 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; } } 89 04/29/2004 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); } } } 90 04/29/2004 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> 91 04/29/2004 faces-config.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!-- Validator --> <validator> <description> Registers the concrete Validator implementation, carstore.FormatValidator with the validator identifier, FormatValidator. </description> <validator-id>FormatValidator</validator-id> <validator-class>carstore.FormatValidator</validator-class> <attribute> <description> List of format patterns separated by '|'. The validator compares these patterns against the data entered in a component that has this validator registered on it. </description> <attribute-name>formatPatterns</attribute-name> <attribute-class>java.lang.String</attribute-class> </attribute> </validator> 92 04/29/2004 Converter 93 04/29/2004 Converter ? CreditCardConverter.java – Accepts a Credit Card Number of type String and strips blanks and "-" if any from it 94 04/29/2004 CreditCardConverter in CarStore 95 04/29/2004 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]); } 96 04/29/2004 faces-config.xml <!-- 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> 1 97 04/29/2004 Custom Components & Renderer 98 04/29/2004 Custom Component ? AreaComponent.java – The class that defines the component corresponding to the area custom tag 99 04/29/2004 Renderer ? AreaRenderer.java – This Renderer performs the delegated rendering for the UIArea component 100 04/29/2004 Custom Tag Files, TLD files 101 04/29/2004 Custom Tag Classes ? AreaTag – ? ImageArea – ? bean that stores the shape and coordinates of the hot spots MapComponent – ? tag handler that implements the area custom tag class that defines the component orresponding to the map custom tag MapTag – tag handler that implements the map custom tag 102 04/29/2004 TLD file ? carstore.tld – Defines carstore.FormatValidatorTag 103 04/29/2004 Stylesheet 104 04/29/2004 Stylesheet ? stylesheet.css 105 04/29/2004 storeFront.jsp (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 13 <HTML> <HEAD> <TITLE>Welcome to CarStore</TITLE> <link rel="stylesheet" type="text/css" href='<%= request.getContextPath() + "/stylesheet.css" %>'> </HEAD> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <BODY BGCOLOR="white"> <f:loadBundle basename="carstore.bundles.Resources" var="bundle"/> 106 04/29/2004 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" column 1 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 2 107 04/29/2004 stylesheet.css (page 1) 1 2 3 4 5 6 7 8 9 10 11 12 ... .top-table { padding: 0; border: 0; width: 660px; } .storeFrontCar { padding: 0 border: 0 } ... 108 04/29/2004 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 } 109 04/29/2004 stylesheet.css (page 2) 1 2 3 4 5 6 7 8 9 ... .package-selected { background-color: #93B629; } .package-unselected { background-color: #C0C0C0; } ... 110 04/29/2004 Configuration Files 111 04/29/2004 faces-config.xml 1 2 3 4 5 6 7 8 9 10 11 12 <faces-config> <application>...</application> <validator>...</validator> <converter>...</converter> <managed-bean>...</managed-bean> ... <managed-bean>...</managed-bean> <navigation-rule>...</navigation-rule> ... <navigation-rule>...</navigation-rule> </faces-config> 112 04/29/2004 faces-config.xml (page2) 1 2 3 4 5 6 7 8 9 <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> 113 04/29/2004 Images 114 04/29/2004 ? 115 04/29/2004 ? duke.gif 116 04/29/2004 ? 117 04/29/2004 ? 118 04/29/2004 Passion! 119