Section 16.4. Root Application Files

   

16.4 Root Application Files

The root of the application is the <TOMCAT_HOME>webapps/store folder. Individual files are prefixed with "Listing." Folder names are indicated in this chapter by top-level headers.

16.4.1 index.jsp

 <%--     template: index.jsp    purpose: view default page    use: called as index when site is requested. Just has link      to the catalog. --%> <jsp:include page="header.jsp" flush="true" />           <%-- begin middle content --%> <tr> <td align="center" valign="top" width="445"> <table cellpadding="0" cellspacing="0" border="0" width="445" align="center"> <tr> <td width="98">&nbsp;</td> <td><br>welcome to our online store. <br> <br>  <a href="viewCatalog.jsp">View the catalog</a>  </td> </tr> </table> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" flush="true" /> 

The index.jsp file acts as the default file in the application. It simply includes header and footer files, as well as a side navigation bar. The main thing it does is show a link to viewCatalog.jsp , which is where the store application really begins. The application was set up this way so that you can define specials in the database and show them here, or use this as an informative page.

16.4.2 header.jsp

 <%--     template: header.jsp    purpose: set html head info    use: --%>  <% String base = "http://localhost:8080/store/"; %>  <html> <head>     <title>ecommerce site</title>     <link rel="stylesheet" type="text/css"         href="styles/main.css" title="Store">  <base href="<%= base %>">  </head> <body topmargin="0" leftmargin="0" marginwidth="0"     marginheight="0" background="images/bglines.gif"> <!--Main Table--> <table cellpadding="0" cellspacing="0"        border="0" width="764" align="left"        background="images/spacer.gif"> <tr> <td bgcolor="#FFFFFF" valign="top" width="763" align="left"> <table cellpadding="0" cellspacing="0" border="0" width="763">             <!--Header And Navigation--> <tr>    <td colspan="3" align="left">      <table cellpadding="0" cellspacing="0" border="0"          width="100%">          <tr>             <td align="left" width="184">                <a href="<%= base %>" border="0">                   <img src="images/logo.gif" alt=""                     width="184" height="59" border="0"></a>             </td>             <td width="255" height="59">                 <img src="images/spacer.gif"                     width="225" height="59">             </td>             <td align="right" valign="bottom">        <!-- links or images can go here --> <br> <a href="http://mysite.com">home</a> <br>                </td>            </tr>            <tr>               <td colspan="3" height="147">                  <img src="images/trail.jpg" width="764"                      height="102">                  <br>                  <img src="images/spacer.gif" width="50"                      height="1">                  <img src="images/storeHeader.gif">                </td>            </tr>          </table>        </td>      </tr> 

The file header.jsp consists primarily of static HTML. We define a base link that you would need to change for production. All store pages will include this file ”except for those in the checkout process, which use a slightly different header that includes JavaScript form validation.

16.4.3 sideNav.jsp

 <%--     template: index.jsp    purpose: show default page    use: called as index when site is requested. --%> <table border="0" width="200" height="300" cellspacing="5">     <tr>         <td valign="top" align="right">  <a href="viewCart.jsp">view cart   </a>&nbsp;<br>   <br>   <a href="viewCatalog.jsp">continue shopping   </a>  &nbsp;<br>         </td>     </tr> </table> 

This file is another static page that just allows you to define a separate navigation bar on the right-hand side of the screen. Its purpose is to give the user links to view the items in his or her cart and to return to the catalog to continue shopping after he or she has added an item.

16.4.4 footer.jsp

 <%--     template: footer.jsp    purpose: include footer HTML    use: included from index.jsp --%>     <tr>         <td colspan="3" valign="bottom"             valign="right"><br><br><br><br><br><br>             <table cellpadding="0" cellspacing="0" border="0"                  width="763" align="center">                 <tr>                     <td colspan="3" align="center">                       <span class="greytext">                         online store                       </span>                    </td>                 </tr>                 <tr>                     <td width="34" bgcolor="#000000">                         <img src="images/spacer.gif"                              alt="" width="34"                              height="15" border="0">                     </td>                     <td width="32" bgcolor="#666666">                         <img src="images/spacer.gif"                             alt="" width="32" height="15"                             border="0">                     </td>                     <td width="32" bgcolor="#CC0000">                         <img src="images/spacer.gif"                             alt="" width="32" height="15"                             border="0">                     </td>                 </tr>             </table>         </td>     </tr>     </table> </td> <td bgcolor="#000000" width="1" align="left">     <img src="images/spacer.gif"        alt="" width="1" border="0"> </td> <td>&nbsp;</td> </tr> </table> </body> </html> 

The footer.jsp file ends the display, and it consists exclusively of HTML design elements, all of which you'll want to replace when using your own design.

16.4.5 viewCatalog.jsp

[View full width]
 
[View full width]
<%-- template: viewCatalog.jsp purpose: show categories, products in subcategories and product details. Allows user to add items to cart. use: called when user clicks link on index. This is the homepage of the store. --%> <%@ page import = "java.sql.ResultSet, java.util.*, java.text.*" %> <%--BEAN TO NAVIGATE CATALOG--%> <jsp:useBean id="catalog" class = "com.cybertrails.store.beans.CatalogBean" graphics/ccc.gif scope="request"/> <jsp:include page = "header.jsp" /> <tr> <td width="25"><img src="images/spacer.gif" width="25"/> </td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> Categories:<br> <%-- This scriptlet connects to the database and gets the categories. Then loop over the graphics/ccc.gif result and set name and id into local variables to be output on the page --%> <% catalog.connect(); ResultSet rs = catalog.getCategories(); while (rs.next()) { String catname = rs.getString("catname"); String catid = rs.getString("catid"); %> <table width="400" border="0"> <tr> <td align="left"> <span class="title1"> <a href="viewSubs.jsp?catid=<%= catid %>"> <%= catname %> </a> </span> <br> </td> </tr> </table> <%--end while loop --%> <% } %> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" />

This page uses a JavaBean (defined in the source file CatalogBean.java ) to connect to the database and get a result containing all of the category names. Once we've got this, we loop over them and output them. We also build the link dynamically so that we can pass the categoryID as a parameter. Our categories page is shown in Figure 16.1.

Figure 16.1. The categories page.

graphics/16fig01.jpg

Note

One thing to note about these catalog files is that they reintroduce the bean and reconnect to the database each time. Refactoring this aspect of the code to make this process more efficient is left as an exercise for the reader.


16.4.6 viewSubs.jsp

 <%--     template: viewSubs.jsp    purpose: show subcategories in chosen product category    use: called when an ID param is passed from the      viewCategory.jsp --%> <%@ page import = "java.sql.ResultSet, java.util.*, java.text.*" %> <%--BEAN TO NAVIGATE CATALOG--%>  <jsp:useBean id="catalog" class =   "com.cybertrails.store.beans.CatalogBean" scope="request"/>  <jsp:include page = "header.jsp" /> <tr>     <td width="25"><img src="images/spacer.gif" width="25"/></td>     <td valign="top" width="487">         <br>&nbsp;         <img src="images/bgspacertest.gif" width="487" height="1"/>         Subcategories:<br>  <%   catalog.connect();   ResultSet   rs = catalog.getSubCategories(request.getParameter("catid"));   while (rs.next()) {   String subcatname = rs.getString("subcatname");   String subcatid = rs.getString("subcatid");   %>  <table width="400" border="0">              <tr>                 <td align="left">                     <span class="title1">  <a href="viewProducts.jsp?subcatid=<%= subcatid %>">   <%= subcatname %>   </a>  </span>                     <br>                 </td>              </tr>          </table>             <%--end while --%>          <% }   %>     </td>     <td width="250" align="right" valign="top">          <%-- includes menu --%>          <jsp:include page="sideNav.jsp" flush="true" />     </td>    </tr> <jsp:include page="footer.jsp" /> 

The viewSubs.jsp file is almost exactly like viewCategories.jsp . Its purpose is to show the subcategories in a particular category. For example, if you had defined a main category called "Drinks" and then clicked that link in viewCategory.jsp , you would now see all associated subcategories, which might include "Coffee," "Tea," and "Soda." Clicking on one of these subcategories will pass the subcategory ID to the next page, viewProducts.jsp .

16.4.7 viewProducts.jsp

[View full width]
 
[View full width]
<%-- File: viewProducts.jsp Purpose: show products in a chosen subcategory --%> <%@ page import = "java.sql.ResultSet, java.util.*, java.text.*" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/ea/core" %> <%--BEAN TO NAVIGATE CATALOG--%> <jsp:useBean id="catalog" class = "com.cybertrails.store.beans.CatalogBean" graphics/ccc.gif scope="request"/> <jsp:include page = "header.jsp" /> <tr> <td width="25"><img src="images/spacer.gif" width="25"/></td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> Products:<br> <% catalog.connect(); ResultSet rs = catalog.getProducts(request.getParameter("subcatid")); while (rs.next()) { String name = rs.getString("name"); String productid = rs.getString("productid"); String price = rs.getString("price"); String shortdescription = rs.getString("shortdescription"); String smimage = rs.getString("smimage"); %> <table width="400" border="0"> <tr> <td align="left"> <span class="title1"> <a href="viewProductDetail.jsp?productid=<%= productid %>"> <%= name %> </a> </span> <span class="txt"> <br>price: $<%= price %> <br>description: <%= shortdescription %> <br>image: <%= smimage %> </span> <br> </td> </tr> </table> <%--end while --%> <% } %> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" />

This file is very much like its predecessors. It shows you all of the products in a particular subcategory, as shown in Figure 16.2. The product links are also dynamically built in the same manner. Clicking on one of the product names takes you to a detail page for that product, viewProductDetail.jsp .

Figure 16.2. The list of products and their short descriptions in a given subcategory.

graphics/16fig02.jpg

I don't have any images for these products, so in these product pages I have just output the name of the image stored as a path in the database. This is a very common way to deal with images that need to be referenced dynamically. The only adjustment you need to make is to output the value into the "src" attribute of an HTML <img> tag instead of printing it directly to the browser.

16.4.8 viewProductDetail.jsp

[View full width]
 
[View full width]
<%-- template: viewSubs.jsp purpose: show subcategories in chosen product category use: called when a param is passed from viewSubs.jsp --%> <%@ page import = "java.sql.ResultSet, java.util.*, java.text.*" %> <%--BEAN TO NAVIGATE CATALOG--%> <jsp:useBean id="catalog" class = "com.cybertrails.store.beans.CatalogBean" graphics/ccc.gif scope="request"/> <jsp:include page = "header.jsp" /> <tr> <td width="25"><img src="images/spacer.gif" width="25"/> </td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> <% catalog.connect(); ResultSet rs = catalog.getOneProduct(request.getParameter("productid")); String productName = ""; while (rs.next()) { String productid = rs.getString("productid"); productName = rs.getString("name"); String price = rs.getString("price"); String longdescription = rs.getString("longdescription"); String lgimage = rs.getString("lgimage"); %> <table width="400" border="0"> <tr> <td align="left"> <span class="title1"><%= productName %> </span> <br>price: $<%= price %> <br>description: <%= longdescription %> <br>image: <%= lgimage %> <br> </td> </tr> </table> <%-- End While --%> <% } %> <form action="doCart.jsp" method="POST"> <table width="400" border="0"> <%-- get product option set --%> <% ResultSet ors = catalog.getProductOptions(request.getParameter("productid")); String currentOptionSet = ""; while (ors.next()) { String optionsetid = ors.getString("optionsetid"); String optionsetname = ors.getString("optionsetname"); String optionid = ors.getString("optionid"); String optionname = ors.getString("optionname"); String optionpriceadd = ors.getString("priceadd"); %> <tr> <td align="left"> <!--this acts like <cfquery group="">. without it, the option set name would be displayed next to every option--> <% if(!(currentOptionSet.equals(optionsetname))) { currentOptionSet = optionsetname; %> <br><b><%= optionsetname %></b><br> <% } %> <input type = "radio" name="oset<%= optionsetid %>" value = "<%= optionname %><%= optionpriceadd %> <%= optionid %>"> <%= optionname %> (add: $<%= optionpriceadd%>) </td> </tr> <%--end while --%> <% } %> </table> <br> <table width="400" border="0"> <tr> <td align="left"> <input type="hidden" name="productid" value="<%= request.getParameter("productid") %>"> <input type="hidden" name="productName" value="<%= productName %>"> <input type="hidden" name="action" value="add"> <input type="text" name="quantity" value="1" maxlength="2" size="2"> <input type="submit" name="submit" value="add to cart"> <br> </td> </tr> </table> </form> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" />

This is an important listing. Its job is to show detailed information about a product. Detail information in this case means a long description, a bigger picture, and the options associated with a product. Few demonstration stores will show how to successfully implement this aspect of online shopping, despite the fact that it is a prevalent part of real online shopping. Options represent choices the shopper should make about the product. For instance, a shirt would require at least two option sets: color and size. Within each of these option sets, you need to define the individual options that the user can choose from, such as red or blue, and S, M, L, or XL. This is all done in the database design, though it makes our checkout and completed order-retrieval page a touch trickier.

Note

Here is one thing you almost certainly want to change in this file if you implement this store in production: Right now, no options are checked by default. So a shopper could order an item without specifying any options if he or she wasnt paying attention. For instance, you could receive an order for a laptop with no hard drive size specified. Now, I know that users are conscientious , careful, savvy creatures who always read all of the instructions. But on some rare occasion, there is a slim chance of this happening. Because the options are output in a loop, youd probably want to add some conditional logic to check against a MOD.


Note that the value of the option radio button gets dynamically set. The value includes a delimited list including the name of the option, the option set it is in, and the amount of money that choosing this option adds to the price of the current product. See Figure 16.3 for our product detail page.

Figure 16.3. The product detail view.

graphics/16fig03.jpg

This also affords a nice opportunity to show how to deal with nested query outputs. In ColdFusion, you can simply call another <cfoutput> and use its group attribute. Because JSP has no such built-in mechanism, we home grow it this way.

Once a shopper has viewed an item, he or she can add it to the cart with the link, or return to another page to continue shopping. The link hits doCart.jsp , the next listing.

16.4.9 doCart.jsp

 <%--     template: doCart.jsp CUSTOM TAG CALLER    purpose: perform any necessary action in the cart and       forward request to viewCart    use: ADD or REMOVE an item: <cart:product action="addremove" productid = "productid"/> VIEW the contents of the cart: <cart:product action="view"/> --%>  <%@taglib prefix="cart" uri="/WEB-INF/cart.tld" %>   <%@taglib prefix="c" uri="http://java.sun.com/jstl/ea/core" %>  <% String productid = request.getParameter("productid"); %>  <c:choose>   <c:when test="${param.action == 'add'}">   <cart:product action="add" productid = "<%= productid %>"/>   </c:when>   <c:when test="${param.action == 'remove'}">   <cart:product action="remove" productid = "<%= productid %>"/>   </c:when>  <c:otherwise>                 <cart:product action="view"/>             </c:otherwise>         </c:choose> <%--now that processing is done,     forward to the view page to see cart.     like using <cflocation>--%> <jsp:forward page="viewCart.jsp" /> 

This file uses the when/otherwise tags in the JSTL. These tags act like < cfswitch > and <cfcase> in some regards. Here they are used to determine whether or not the user wants to add or remove something from the cart. If the request parameter "action" was specified, then the <c:when> clause that matches it calls the product tag with the appropriate attribute values. The page then forwards control to viewCart.jsp , which shows the contents of the cart and gives the user the option to check out. The viewCart page is shown in Figure 16.4.

Figure 16.4. The viewCart page, showing the item and options selected, quantity, price, and subtotal . The user is given the option to remove the item or checkout.

graphics/16fig04.jpg

16.4.10 viewCart.jsp

 <%--      File: viewCart.jsp     Purpose: show the contents of the cart.     Use: this page is called after every interaction with the     cart so that the user can see the updates. --%> <%@ page import = "java.sql.ResultSet, java.util.*, java.text.*" %> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <jsp:include page = "header.jsp" />   <tr>     <td width="25"><img src="images/spacer.gif" width="25"/>     </td>     <td valign="top" width="487">         <br>&nbsp;         <img src="images/bgspacertest.gif" width="487"               height="1"/>         <h1>Shopping Cart</h1>  <cart:view />   <%   ArrayList currentItems =   (ArrayList)session.getAttribute("currentItems");   if (currentItems != null && currentItems.size() != 0 ) {   %>   <table border="0" width="450">   <tr>   <td bgcolor="white" align="right">   <a href="checkout.jsp"><b>checkout</b></a>   </td>   </tr>   </table>   <% // close if   } %>  <br>     </td>     <td width="250" align="right" valign="top">          <%-- includes menu --%>          <jsp:include page="sideNav.jsp" flush="true" />     </td>    </tr> <jsp:include page="footer.jsp" /> 

The bold font in the viewCart listing shows the call to the <cart:view> custom tag. This tag writes out the HTML table that displays the contents of the cart directly where it is called from. Then we check the size of the cart. If it is null, then it hasn't been created yet; if it has no items in it, then its size is 0. If either of these conditions is true, then we do not show the checkout link. If there is something in the user's cart, we show the link to checkout.jsp .

16.4.11 checkout.jsp

 <%--      File: checkout.jsp     Purpose: this file starts the checkout process     Use: we arrive here when the user clicks "checkout" on       viewCart.jsp. --%> <%@ page import="java.util.*" %> <%     Enumeration ses = session.getAttributeNames();     if (ses != null) {     out.println("SESSION SCOPE: <br>");     while(ses.hasMoreElements()) {       out.println (ses.nextElement() + "<br>");   } }     else out.println ("nothing in session"); %> <jsp:forward page="viewBilling.jsp" /> 

Note

Nothing actually happens in checkout.jsp . The file forwards to viewBilling.jsp , which shows the form to the user to enter billing information. What the file does do is enumerate over the session. I include it here because this was useful during development, and, after all, this is a case study. Because the request gets forwarded to viewBilling , nothing will actually print to the browser from checkout.jsp . In your own application, you would remove this page and forward directly to viewBilling ”unless there was some logging or cleanup work that you wanted to do here.


Let's interject this little utility script right here. This scriptlet is not a necessary part of the e-commerce site, but you can use this scriptlet, which acts like a call to <CFDUMP var=#session#> by just printing out what's in the session:

 <%@page import="java.util.*">  <% Enumeration ses = session.getAttributeNames(); Object temp;   if (ses != null) {     out.println("SESSION SCOPE: <br>");       while(ses.hasMoreElements()) {         temp = ses.nextElement();         out.println(temp.toString() + ": " +         session.getAttribute(temp.toString()) + "<br>");       }   }   else out.println("nothing in session"); %> 

16.4.12 viewBilling.jsp

[View full width]
 
[View full width]
<%@page contentType="text/html"%> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <jsp:include page="headerWithValidation.jsp" flush="true"/> <tr> <td width="25"><img src="images/spacer.gif" width="25"/> </td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> <h1>Billing Info</h1> <%-- show form for billing input--%> <table width="450" border="0" cellspacing="0" cellpadding="0"> <tr> <td colspan="2" valign="top"> Please take your time filling out the following information. If you are placing an online order via credit card, your billing information should graphics/ccc.gif appear as it does on your Credit Card billing statements. You will have opportunities to cancel your order after this step. <form name="Billing_Form" onSubmit="return checkBillingForm(this)" action="doBilling.jsp" graphics/ccc.gif method="POST"> <table width="450" align="center" border="0"> <tr> <td colspan="2" align="center" bgcolor="#CC0000" class="cartHeaders2">Billing graphics/ccc.gif Information<br></td> </tr> <tr> <td align="left" width="110">Name<br></td> <td><INPUT TYPE="Text" NAME="bName" SIZE="25" MAXLENGTH="100" onBlur="validfn(bName. graphics/ccc.gif value)"><br></td> </tr> <tr> <td align="left" align="top">Address<br></td> <td><textarea cols=23 rows=2 wrap="virtual" name="bAddress" style="font-size: 11; graphics/ccc.gif font-family: arial, helvetica, sans-serif; height: 40; width: 190;"></textarea><br></td> </tr> <tr> <td align="left">City<br></td> <td><INPUT TYPE="Text" NAME="bCity" SIZE="25" MAXLENGTH="50"><br></td> </tr> <tr> <td align="left">State<br></td> <td> <SELECT NAME="bState" SIZE="1"> <jsp:include page="states.jsp" /> </SELECT> <br> </td> </tr> <tr> <td align="left">Zip Code<br></td> <td><INPUT TYPE="Text" NAME="bZipCode" SIZE="25" MAXLENGTH="10" onClick="validZip(zip. graphics/ccc.gif value)"><br></td> </tr> <tr> <td align="left">Country<br></td> <td><INPUT TYPE="Text" NAME="bCountry" SIZE="25" MAXLENGTH="100" VALUE="USA"><br></td> </tr> <tr> <td align="left">Phone<br></td> <td><INPUT TYPE="Text" NAME="bPhone" SIZE="25" MAXLENGTH="50"><br></td> </tr> <tr> <td align="left">E-mail<br></td> <td><INPUT TYPE="Text" NAME="bEmail" SIZE="25" MAXLENGTH="100"><br></td> </tr> <tr> <td colspan="2"><hr width="100%" size="3" color="#666666"></td> </tr> <tr> <td colspan="2" align="right"> <input type="submit" value="Go to the Next Step" style="font-size: 11; font-family: graphics/ccc.gif Verdana; width: 180;"><br></td> </tr> </table> </form> </td> </tr> </table> <br> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" flush="true"/>

This page is standard HTML for the most part; it appears as shown in Figure 16.5. The only two items of note are the following: First, we include the list of states to populate the form. Second, we use a different header, headerWithValidation.jsp . That header, shown below, includes some JavaScript to make sure that something is entered in the form.

Figure 16.5. The billing information page.

graphics/16fig05.jpg

16.4.13 headerWithValidation

[View full width]
 
[View full width]
<%-- Template: headerWithValidation.jsp Purpose: included HTML header. The only difference between this and header.jsp is that this includes JS to validate form data entered by user. Use: Called from shipping, billing, and confirm templates instead of the header.jsp --%> <% String base = "http://localhost:8080/store/"; %> <html> <head> <title>ecommerce site</title> <link rel="stylesheet" type="text/css" href="styles/main.css" title="CyberTrails"> <base href="<%= base %>"> <!-- validates form fields --> <script language="JavaScript"> function checkBillingForm(form) { var emailFilter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\. graphics/ccc.gif [a-z]{2})?)$/i if(form.bName.value == "") { alert("You must enter a billing name.") return false } else if(form.bAddress.value == "") { alert("You must enter a billing address.") return false } else if(form.bCity.value == "") { alert("You must enter a billing city.") return false } else if(form.bZipCode.value == "") { alert("You must enter a billing zipcode.") return false } else if(form.bCountry.value == "") { alert("You must enter a billing country.") return false } else if(!emailFilter.test(form.bEmail.value)) { alert("Please enter a valid email address") return false } } function checkShippingForm(form) { var emailFilter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\. graphics/ccc.gif [a-z]{2})?)$/i if(form.sName.value == "") { alert("You must enter a shipping name.") return false } else if(form.sAddress.value == "") { alert("You must enter a shipping address.") return false } else if(form.sCity.value == "") { alert("You must enter a shipping city.") return false } else if(form.sState.value == "") { alert("You must enter a shipping state.") return false } else if(form.sZipCode.value == "") { alert("You must enter a shipping zipcode.") return false } else if(form.sCountry.value == "") { alert("You must enter a shipping country.") return false } else if(!emailFilter.test(form.sEmail.value)) { alert("Please enter a valid email address") return false } } </script> </head> <body topmargin="0" leftmargin="0" marginwidth="0" marginheight="0" background="images/ graphics/ccc.gif bglines.gif"> //... rest of file omitted...

The JavaScript validation is the only item of interest here, and the rest of the file is just the same HTML from header.jsp . Once the form is submitted, it goes to doBilling.jsp to process the request.

16.4.14 states.jsp

 <!-- list of states for inclusion       in the select box for billing and shipping forms.   --> <OPTION VALUE="AL">Alabama</OPTION> <OPTION VALUE="AK">Alaska</OPTION> ...// some states omitted <OPTION VALUE="WY">Wyoming</OPTION> <OPTION VALUE="INT">International</OPTION> 

This file simply contains a list of all the state abbreviations and names. It is used to populate the form on viewBilling.jsp .

16.4.15 doBilling.jsp

 <%--      File: doBilling.jsp     Purpose: this file accepts request params from the     viewBilling page and calls the checkout tag.     Control is then forwarded to the next step,     which is shipping info (if info is different than billing)     or payment info (if the same). --%> <%@ page contentType="text/html"%> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <html> <head><title>ecommerce</title></head> <body> <%-- do the shipping insert action--%>  <cart:checkout action="billing" />  <%--forward to display page for next step--%> <jsp:forward page="viewShipping.jsp" /> </body> </html> 

This file accepts request parameters from the viewBilling page and calls the checkout tag to add the parameters to the session object.

16.4.16 viewShipping.jsp

[View full width]
 
[View full width]
<%-- File: viewShipping.jsp Purpose: enter shipping information. The data entered in billing is all spilled over into this form so that users don't have to re-enter if it is the same. --%> <%@page contentType="text/html"%> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <jsp:include page="headerWithValidation.jsp" flush="true"/> <tr> <td width="25"><img src="images/spacer.gif" width="25"/></td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> <h1>Shipping/Setup Info</h1> <%-- show form for shipping input--%> <table width="450" border="0" cellspacing="0" cellpadding="0"> <tr> <td colspan="2" valign="top"> If you have ordered <b>products</b>, they must be shipped to you or someone else. Please enter the correct shipping information below.<br> <br> If you have ordered <b>services</b> (such as Web hosting), they do not require shipping, graphics/ccc.gif they require setup instead.<br> Please make the appropriate selection at the bottom of graphics/ccc.gif this form. <form name="Shipping_Form" onSubmit="return checkShippingForm(this)" action="doShipping. graphics/ccc.gif jsp" method="POST"> <table width="450" align="center" border="0"> <tr> <td colspan="2" align="center" bgcolor="#CC0000" class="cartHeaders2">Shipping/Setup graphics/ccc.gif Information<br></td> </tr> <tr> <td align="left" width="110">Name<br></td> <td> <INPUT TYPE="Text" NAME="sName" SIZE="25" MAXLENGTH="100" value="<%= session. graphics/ccc.gif getAttribute("bName") %>"> <br></td> </tr> <tr> <td align="left" align="top">Address<br></td> <td><textarea cols=23 rows=2 wrap="virtual" name="sAddress" style="font-size: 11; graphics/ccc.gif font-family: arial, helvetica, sans-serif; height: 40; width: 190;"><%= session. graphics/ccc.gif getAttribute("bAddress") %></textarea><br></td> </tr> <tr> <td align="left">City<br></td> <td><INPUT TYPE="Text" NAME="sCity" SIZE="25" MAXLENGTH="50" value="<%= session. graphics/ccc.gif getAttribute("bCity") %>"><br> </td> </tr> <tr> <td align="left">State<br></td> <td> <INPUT TYPE="Text" NAME="sState" SIZE="25" MAXLENGTH="10" value="<%= session.getAttribute( graphics/ccc.gif "bState") %>"><br> <br> </td> </tr> <tr> <td align="left">Zip Code<br></td> <td><INPUT TYPE="Text" NAME="sZipCode" SIZE="25" MAXLENGTH="10" value="<%= session. graphics/ccc.gif getAttribute("bZipCode") %>"><br> </td> </tr> <tr> <td align="left">Country<br></td> <td><INPUT TYPE="Text" NAME="sCountry" SIZE="25" MAXLENGTH="100" value="<%= session. graphics/ccc.gif getAttribute("bCountry") %>"><br> </td> </tr> <tr> <td align="left">Phone<br></td> <td> <INPUT TYPE="Text" NAME="sPhone" SIZE="25" MAXLENGTH="50" value="<%= session. graphics/ccc.gif getAttribute("bPhone") %>"><br> </td> </tr> <tr> <td align="left">E-mail<br></td> <td> <INPUT TYPE="Text" NAME="sEmail" SIZE="25" MAXLENGTH="100" value="<%= session. graphics/ccc.gif getAttribute("bEmail") %>"><br> </td> </tr> <tr> <td align="left" valign="top">Shipping Method<br></td> <td> <input type="radio" name="ShipMethod" value="0"> Services ONLY--no shipping<br> <input type="radio" name="ShipMethod" value="20" checked> Ground (add )<br> <input type="radio" name="ShipMethod" value="27"> Express (add .00)<br> <input type="radio" name="ShipMethod" value="45"> International (add )<br> </td> </tr> <tr> <td colspan="2"><hr width="100%" size="3" color="#666666"></td> </tr> <tr> <td colspan="2" align="right"> <input type="submit" value="Go to the Next Step" style="font-size: 11; font-family: graphics/ccc.gif Verdana; width: 180;"><br></td> </tr> </table> </form> </td> </tr> </table> <br> </td> <td width="250" align="right" valign="top"> <%-- includes menu --%> <jsp:include page="sideNav.jsp" flush="true" /> </td> </tr> <jsp:include page="footer.jsp" flush="true"/>

This file makes use of the values passed from the billing form and set into the session scope. We prepopulate the form using these values so that if the shipping is the same as the billing, the user can simply hit Next and continue the checkout process. Either way, the values are added to the session and ultimately to the database.

16.4.17 doShipping.jsp

 <%@page contentType="text/html"%>  <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <html> <head><title>ecommerce</title></head> <body> <%-- do the shipping insert action--%>  <cart:checkout action="shipping" />  <%--forward to display page for next step--%>  <jsp:forward page="viewConfirm.jsp" />  </body> </html> 

The doShipping file, just like the doBilling file, adds the parameters passed from the request into the session.

Note

We dont add anything to the database until the very last possible minute. This helps make sure we dont have a lot of bad data in our database consisting of half-placed orders. Everything is kept in the session until the last step. We also dont pass anything sensitive, such as product price, as hidden form fields, because they are both easy to exploit and generally difficult to maintain.


16.4.18 viewConfirm.jsp

[View full width]
 
[View full width]
<%-- File: viewConfirm.jsp Purpose: this file shows users what exactly they are purchasing and lets them enter credit card info if the order, billing, and shipping are all correct. Calls tag that calculates tax and adds everything for grand total. Submits to doConfirm.jsp which finalizes the order. --%> <%@page contentType="text/html"%> <%@ page import="java.util.*" %> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <jsp:include page="header.jsp" flush="true"/> <tr> <td width="25"><img src="images/spacer.gif" width="25"/> </td> <td valign="top" width="487"> <br>&nbsp; <img src="images/bgspacertest.gif" width="487" height="1"/> <h1>Confirmation</h1> <table width="450" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="141" rowspan="2" valign="TOP"> <form name="Confirm_form" method="post" action="doConfirm.jsp"> </td> </tr> <tr> <td> <p>Please verify that the following information is correct. The billing information should appear exactly as shown on your credit card. Once you have double-checked that the following information is correct, enter your credit graphics/ccc.gif card information and click "Submit Order" to place your order.</p> <table width="450" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="50%" bgcolor="#CC0000" class="cartHeaders2">Billing Information<br></td> <td width="50%" bgcolor="#CC0000" class="cartHeaders2">Shipping Information<br></td> </tr> <tr> <%-- output billing information--%> <td valign="top"> <%= session.getAttribute("bName") %><br> <%= session.getAttribute("bAddress") %><br> <%= session.getAttribute("bCity") %>, <%= session.getAttribute("bState") %> <%= session.getAttribute("bZipCode") %><br> <%= session.getAttribute("bCountry") %><br> Phone: <%= session.getAttribute("bPhone") %><br> </td> <br><br> </td> <%--output shipping information--%> <td valign="top"> <%= session.getAttribute("sName") %><br> <%= session.getAttribute("sAddress") %><br> <%= session.getAttribute("sCity") %>, <%= session.getAttribute("sState") %> <%= session.getAttribute("sZipCode") %><br> <%= session.getAttribute("sCountry") %><br> Phone: <%= session.getAttribute("sPhone") %><br> </td> </tr> </table> <%-- output the current items in the cart, along with chosen options and subtotal--%> <cart:view /> <%--output shipping, tax, and grand total--%> <table width="450" cellspacing="2" cellpadding="2" border="0"> <tr> <td colspan="3" align="right" bgcolor="#666666" class="cartHeaders">Shipping</td> <td align="right" class="text"> $<%= request.getParameter("ShipMethod") %> <br></td> </tr> <tr> <%--calculate tax if business in this state--%> <td colspan="3" align="right" bgcolor="#666666" class="cartHeaders">Tax</td> <td align="right" class="text"> $<cart:calculate item="tax"/> <br></td> </tr> <tr> <td colspan="3" align="right" bgcolor="#000000" class="cartHeaders">Total</td> <td align="right" class="text"> $<b><cart:calculate item="total"/></b> <br> </td> </tr> </table> <br> <table width="450" cellspacing="2" cellpadding="2" border="0"> <tr> <td colspan="2" bgcolor="#CC0000" align="center" class="cartHeaders2">Credit Card graphics/ccc.gif Information<br></td> </tr> <tr> <td align="right">Name on card:<br></td> <td><INPUT TYPE="Text" NAME="ccName" SIZE="30"><br></td> </tr> <tr> <td align="right">Card number:<br></td> <td><INPUT TYPE="Text" NAME="ccNumber" SIZE="30"><br></td> </tr> <tr> <td align="right">Expiration date:<br></td> <td><INPUT TYPE="Text" NAME="ccExpirationDate" SIZE="10"><br> </td> </tr> </table> <p> <div align="right"> <input type="submit" value="Submit Order" style="font-size: x-small; font-family: Verdana;"> </div> </form> </center> </td> </tr> </table>

This file again makes use of the <cart:view> tag ”the same one used during the shopping process. It is nice to reuse this tag because it makes this step easier, and it makes the app easier to maintain. We just output the shipping and billing information directly to allow the users to confirm what they typed and confirm their entire order. We also use the <cart:calculate> tag to calculate and output the tax and the grand total for the order.

16.4.19 doConfirm.jsp

 <%--      File: doConfirm.jsp     Purpose: this file inserts the completed order,     then redirects to the thank you page. --%> <%@page contentType="text/html"%> <%@ taglib prefix="cart" uri="/WEB-INF/cart.tld" %> <html> <head><title>ecommerce</title></head> <body> <%-- do the shipping insert action--%>  <cart:checkout action="placeOrder"/>  <%--forward to display page for next step--%> <jsp:forward page="viewThankyou.jsp" /> </body> </html> 

Once the user has confirmed his or her purchase, this page calls the <cart:checkout> tag once again, but this time the page passes it to the placeOrder value for the action attribute. This action will take everything in the session (shipping, billing, products ordered, and the options for each product) and distribute it with other miscellaneous order information (such as the tax and grand total) into the correct tables in the database. The confirmation page is shown in Figure 16.6.

Figure 16.6. The confirmation page displaying the shipping and billing information and the complete order. The user enters credit card information here.

graphics/16fig06.jpg

Note

No real-time credit card transaction happens here. You can easily add this functionality to the site because of the way this page is built. Simply add the appropriate account information and code to this page and then insert the order based on the return code. What happens here is that the credit card information is stored directly in the database, and when the order is retrieved, the credit card must be run manually. That poses a slight problem if the credit card fails.


16.4.20 viewThankyou.jsp

 <%--File: viewThankyou.jsp      Purpose: inform the viewers that they successfully checked out. --%> <jsp:include page = "header.jsp" />   <tr>     <td width="25"><img src="images/spacer.gif" width="25"/></td>     <td valign="top" width="487">         <br>&nbsp;         <img src="images/bgspacertest.gif" width="487" height="1"/>         <h1>Thank you</h1> <p align="center"> Thank you for placing an order with us. Your order is complete. </p> <p align="center"> Your order identification number is: <%= session.getAttribute("orderid") %> <br> You may want to print this page or save the number for your records. </p>  <%   // remove session from memory   session.invalidate();   %>  <br>         <br>     </td> <td width="250" align="right" valign="top">          <%-- includes menu --%>          <jsp:include page="sideNav.jsp"/>        </td>    </tr> <jsp:include page="footer.jsp" /> 

Once the user knows the transaction went through, we end the checkout process by destroying his or her session.

The following file, viewCompletedOrder.jsp , is not part of the e-commerce application that the user sees. It is what the merchant uses on the back end to retrieve orders that have been placed.

16.4.21 viewCompletedOrder.jsp

 <%--  File: viewCompleteOrders.jsp Purpose: show a list of all the orders in the database Use: for the admin area of the store Authors: Vic Miller, Eben Hewitt comments: --%> <%@ page import="java.sql.*" %> <%@ page import="java.util.*" %> <jsp:include page = "header.jsp" /> <jsp:useBean id="CompleteOrder" scope="page" class="com.cybertrails.admin.GetOrderBean" />  <%   //Variable Declarations   ResultSet rs;   String isProcessed = "";   String currentOrderID = "0";   // Used to track when we change orders   String currentOPID = "0";   //Used to track when we change products within one order   //Get the complete order list from the database   CompleteOrder.connect();   // if the form has been submitted then process   // the order in the db   if (request.getParameter("orderid") != null) {   isProcessed = CompleteOrder.setIsProcessed(request.getParameter("orderid"));   }   rs = CompleteOrder.getNewOrders();   CompleteOrder.disconnect();   %>  <tr> <td align="center"> <h2><% if (isProcessed.length() > 1) { %>     <%= isProcessed %> <% } %> </h2> </td> </tr>     <td> <% //While loop over the result set to display the orders while(rs.next()) {     //Set the orderid into a string     String orderid = rs.getString("orderid");     //Test to if we have moved onto a new order     if(!orderid.equals(currentOrderID)) {     //Set the currentID to the ID that we are on     currentOrderID = orderid; %> <br><br> <table border="0" cellpadding="0" cellspacing="0" width="95%" align="center">    <tr>      <td bgcolor="#CC9900" align="left" width="50%" colspan="2">          <b>&nbsp;&nbsp;&nbsp;<font color="#ffffff"> Order ID:&nbsp;&nbsp;<%= orderid %></font></b>       </td>    </tr>     <tr>       <td>         <table width="95%" cellpadding="0" cellspacing="0" border="0" align="center">           <tr>             <td><b><i>Billing Information:</i></b></td>           </tr>           <tr> <td>Name:&nbsp;&nbsp;<%= rs.getString("billname") %></td>           </tr>           <tr> <td>Address:&nbsp;&nbsp;<%= rs.getString("billaddress") %></td>           </tr>           <tr> <td>City:&nbsp;&nbsp;<%= rs.getString("billcity") %></td>           </tr>           <tr> <td>State:&nbsp;&nbsp;<%= rs.getString("billstate") %></td>           </tr>            <tr>            <td>Zip Code:&nbsp;&nbsp; <%= rs.getString("billzipcode") %></td>            </tr>            <tr>   <td>Phone:&nbsp;&nbsp;<%= rs.getString("billphone") %></td>            </tr>            <tr>  <td>E-Mail:&nbsp;&nbsp;<%= rs.getString("billemail") %></td>            </tr>          </table>         </td>         <td valign="top">           <table width="95%" cellpadding="0" cellspacing="0" border="0" align="center">                <tr>                  <td><b><i>Shipping Information:</i></b></td>                </tr>                <tr> <td>Name:&nbsp;&nbsp;<%= rs.getString("shipname") %></td>                </tr>                <tr> <td>Address:&nbsp;&nbsp;<%= rs.getString("shipaddress") %> </td>                                     </tr>                                     <tr> <td>City:&nbsp;&nbsp;<%= rs.getString("shipcity") %></td>                    </tr>                    <tr> <td>State:&nbsp;&nbsp;<%= rs.getString("shipstate") %></td>                    </tr>                    <tr> <td>Zip Code:&nbsp;&nbsp;<%= rs.getString("shipzipcode") %> </td>                    </tr>                    <tr> <td>E-Mail:&nbsp;&nbsp;<%= rs.getString("shipemail") %></td>                   </table>                   </td>                   </tr>                  </table> <%-- self-posting form --%> <form name="orderprocessor" method="POST"     action="<%= request.getRequestURL() %>"> <table border="0" width="95%" align="center">    <tr>      <td><br><b><i>Processing Information</i></b></td>    </tr>    <tr>       <td>CC Number:&nbsp;&nbsp; <%= rs.getString("creditnumber") %></td>     </tr>     <tr>      <td>CC Name:&nbsp;&nbsp;<%= rs.getString("creditname") %>      </td>     </tr>     <tr>    <td>CC Exp:&nbsp;&nbsp;<%= rs.getString("creditexpdate") %> </td>     </tr>     <tr>       <td>    <input type="hidden" name="orderid" value="<%= orderid %>">    <input type = "submit" name="process" value="process">       </td>      </tr>      <tr>        <td><hr width="50%" align="left"></td>      </tr>     </table>   </form> <table width="95%" border="0" cellpadding="0" cellspacing="0" align="center">   <tr>      <td><b><i>Product Information:</i></b></td>   </tr> </table> <% } //End of same order if statement %> <% // do a check for each product - check currentOPID if(!currentOPID.equals(rs.getString("ordersproductsid"))) {   //Set the currentOPID to the current product   currentOPID = rs.getString("ordersproductsid"); %> <table width="95%" border="0" cellpadding="0" cellspacing="0" align="center">    <tr>      <td><br>       Product Name:&nbsp;&nbsp;<%= rs.getString("name") %>      </td>    </tr>    <tr>       <td>       Product Price:&nbsp;&nbsp;<%= rs.getString("price") %>       </td>    </tr>    <tr>      <td>       Quantity Ordered:&nbsp;&nbsp;<%= rs.getString("qty") %>      </td>    </tr>    <tr>      <td align="left"><b><i>Options</i></b></td>    </tr>   </table> <% }// End the products if %> <% //Make sure the current optionid is not null then display it    if(rs.getString("optionid") != null) { %> <table width="95%" border="0" cellpadding="0" cellspacing="0" align="center">    <tr>       <td>Option Chosen:&nbsp;&nbsp;          <%= rs.getString("optionname") %></td></td>     </tr>    </table>   <% } //End of option if %> <% }    // End of the While Loop over the Entire Result Set %>     </td> </tr> <jsp:include page="footer.jsp" /> 

The viewCompletedOrder.jsp page gets all of the completed orders that have not yet been processed and outputs them on this page. This page is to be used by the merchant in a password-protected area (you can use the servlet we wrote earlier, perhaps). This page displays all of the information about each unprocessed order along with a Process button. This allows the merchant to view the order, take down the shipping information and product information, fulfill the order, and run the credit card. Then the merchant hits the Process button, which just sets the isProcessed bit in the database to 1 instead of 0. Then it refreshes the page (because it is a self-posting form) in case there are any other orders.

It would be a good idea to show a message if there are no orders initially and to hash all but the last four digits of the credit card.


   
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net