CHAPTER

8

Ajax Case Study

Chapter Objectives

• Integrate various server/client techniques in a comprehensive project

• Experience the callback technique and asynchronous programming

• Practice component-based design of web applications

• Develop abilities of making design decisions based on requirements

8.1 Introduction

 

This chapter presents to you many exciting server/client techniques for implementing powerful and user-friendly Ajax web applications. The use of Ajax features allows rich user experiences. With Ajax, the interaction between users and web applications will no longer be restricted to the simple request–response model.

Via hands-on experiences with the sophisticated case study project of this chapter, you will have opportunities to practice many technical aspects of Ajax. For example, remote asynchronous calls can be placed using many different methods: raw XMLHttpRequest (XHR) calls and XHR wrappers (e.g., those provided by Dojo and Google Maps). Data can be translated in many different forms, e.g., plain text, HTML snippet, and JSON. You will have access to many available technical options and will make decisions in the design process.

Although the application of Ajax technique is the major concern of this chapter, the traditional web application techniques must be smoothly integrated with new Ajax techniques. In this chapter, you will learn how to establish the background database by using SQL (Structured Query Language) scripts and retrieving data by using JDBC (Java Database Connectivity). As required by Ajax, server-side techniques are necessary for generating dynamic content. You will have access to several well-known server-side techniques such as Java Server Page (JSP) and Java servlets. At the server side, you will use Java to dynamically generate HTML code that is rendered in the user's browser. Component-based programming has begun to emerge as a paradigm. On both ASP.Net- and Java-based web application development platforms, server control-based techniques are popular. With server-side controls embedded in a web page, the web server run time (e.g., ASP.Net1 and JavaEE2) can automatically maintain the session state and generate HTML code for server controls. The server-control technique can greatly improve code reuse and increase the developer's productivity. You will also have access to the recent progress in this area, e.g., the JavaServer Faces (JSF). Table 8.1.1 summarizes the various techniques that you will experience in this chapter.

1http://www.asp.net.

2http://java.sun.com/javaee.

Table 8.1.1 Overview of Techniques in Chapter 8

images

We have chosen the Java platform for implementing the case study project because of the many open-source tools available. Throughout the chapter, you will use the following tools:

• NetBeans 6.0.1

• Sun Java System Application Server 9.0 (code name GlassFish2)

• Apache JavaDB (included in NetBeans)

The version of NetBeans should be at least 6.0.1. NetBeans can be downloaded from the NetBeans website at http://www.netbeans.org. It is recommended to download the complete version of NetBeans, which includes all features (and hence GlassFish and JavaDB). To run NetBeans smoothly, you should have at least 1 GB of memory available.

To facilitate your learning process, the source code of the case study project is available for download at this book's website. There are multiple milestones of the project. By downloading and installing a milestone project, you can resume the development of the case study project from any section in the chapter.

8.2 Case Study: BigPeachYardSaleExpress

 

The Big Peach is a metropolitan area with a population of more than 10 million people. Every day, there are hundreds of people moving and selling items in yard sale events. A group of yard sale hobbyists decide to build a dynamic website for helping yard sale organizers to publish information.

The website will assist buyers in better planning their weekend shopping trip. Designers decide to incorporate the following features in their website, which is named BigPeachYardSaleExpress.com:

• Sellers can post information (e.g., location and date) of yard sale events.

• Sellers can post the name, price, and thumbnail image of each item for sale.

• Buyers can search sale events by date and distance from their home address.

• Buyers can visually identify sale events on a map, browse items for sale, and lock/buy items.

• Based on the collection of items locked in a buyer's shopping cart, an itinerary (with driving directions) can be automatically generated for the buyer. The buyer can choose to customize the itinerary by dragging and dropping items.

• BigPeachYardSaleExpress will rely on income from advertising. A dynamic advertisement banner will be placed on each page. The contents of the ad banner will be updated periodically (every 2 seconds). The system should allow easy inclusion of new banner content on the fly.

• The user interface of BigPeachYardSaleExpress should be visually appealing.

A comprehensive website must be established to satisfy these requirements. You will have to complete the following technical components:

1. A background database to store sales event information. You will use an open-source database tool called JavaDB, with internal support from NetBeans.

2. A web application that generates dynamic contents at the server side. There are many technical solutions for this purpose (e.g., PHP, cgi-bin, JSP, servlet, and ASP.Net). You will use Java-based technology because of its popularity and market share.

3. A rich client-side user interface. In addition to the Ajax techniques, there are many other competing technical solutions for providing appealing visual effects to users, e.g., Adobe Flash and Java Applet.

The strength of Ajax is its collection of open standards and the many open-source development tools available. For the animation requirement for the dynamic ad banner, the Dojo animation package will suffice.

8.3 High-Level Design

 

In the requirements of BigPeachYardSaleExpress, the next step is to complete its high-level design. In general, the high-level design of a web application consists of two components: (1) devising a Graphical User Interface (GUI) and (2) designing a database schema. These two components will be covered in the next two subsections.

8.3.1 GUI Design

Figure 8.3.1 displays the general architecture of the website that you are going to implement. The first page of the website is a static page that redirects buyers and sellers. Seller.jsp serves sellers and uses PostItem.jsp to upload information of items for sale. Buyer.jsp serves buyers. As you will see later, this page will be implemented using mainly client-side techniques to maximize rich user experiences. The static web page called MapIDE.html is used to display the Google map. The page allows displaying sale event information dynamically. In the following, the functionality of each page in Figure 8.3.1 will be examined.

8.3.1.1 Portal Page

Page1.jsp is the portal page. As shown in Figure 8.3.2, it consists of two parts: the dynamic header and the main body. The header is a dynamic advertisement banner. Every 2 seconds, the banner will download its contents from the server. The banner can display animation effects over static pictures, e.g., scroll in and scroll out. The main body of the portal page contains two hyperlinks that redirect buyers and sellers to the corresponding service pages. A Cascading Style Sheet (CSS) is defined for these links. For example, when the mouse is moved over the links, both links will have their fonts and color changed to attract users.

images

Figure 8.3.1

General Architecture of BigPeachYardSaleExpress

images

Figure 8.3.2

Portal Page

images

Figure 8.3.3

Portal Page

8.3.1.2 Seller Page

The GUI design of the seller page (Seller.jsp) is displayed in Figure 8.3.3. The seller page also consists of two parts: the dynamic ad banner and the main body. It allows a seller to provide information of a yard sale event. The page is built using Visual Web Pack server controls, e.g., text box, system error message panel, and date–time select box. The NetBeans Visual Web Pack allows designers to conveniently drag and drop controls to complete GUI design. These controls have many useful functions implemented by default. For example, any exceptions thrown by any component of the page, if not specifically handled by any user code, will be nicely sorted and displayed in the system error message panel. Also, the textbox controls (unlike traditional HTML text inputs) provide data type conversion and various validation approaches (such as regular expression validators).

images

Figure 8.3.4

Page for Posting Items for Sale

8.3.1.3 Page for Posting Items

PostItem.jsp is responsible for uploading the information of each item for sale. Once a seller clicks the submit button in Seller.jsp, the seller is redirected to the PostItem.jsp page. The GUI design of PostItem.jsp is shown in Figure 8.3.4. The page allows sellers to upload images of each item to the database. Once an item is saved, it is automatically displayed in the data table at the bottom of the page. The data table is a server control provided by the Visual Web Pack. With little coding effort, programmers can retrieve and display data conveniently by using the data table control. When implementing PostItem.jsp, you will appreciate the power and simplicity of server controls. In the design of the buyer page, on the other hand, you will realize the agility and rich user interface made possible by the use of Java Servlets. You will choose the right technique at the right time, based on the requirements of the project.

images

Figure 8.3.5

The Map IDE for Buyer

8.3.1.4 Buyer Page

Buyer.jsp is probably the most complex page in the project. Similar to the other pages, Buyer.jsp consists of two parts: the ad banner (which is a JavaServer Faces web page fragment) and the main body (which consists of an HTML file called MapIDE.html). The GUI design of MapIDE.html is shown in Figure 8.3.5. MapIDE.html uses pure client-side JavaScript technology and relies on the Dojo framework and the Google Maps service for providing a stunning visual appearance.

As shown on the left side of Figure 8.3.5, MapIDE.html has three toolboxes (which are implemented using Dojo Accordion Panes): Buyer Info, Shopping Cart, and Itinerary. The Buyer Info pane allows a buyer to enter the information of his or her home address and to search yard sale events within a certain radius. The Shopping Cart pane lists the items in the shopping cart (price and thumbnail image), as well as the total price of all items in cart. Buyers can add and drop items in the shopping cart conveniently. The Itinerary pane displays the itinerary of the buyer. Buyers can adjust their itinerary by using drag and drop. If a buyer specifies the planned duration of stay for each stop in the itinerary, the departure and arrival time will be automatically calculated for each stop, based on the driving distance/time information from the Google Maps service. Clicking the Load Direction button will display multiple-point driving directions. On the right-hand side of the window, all the related sale events that satisfy the query criteria are presented. Clicking any sale event displays a list of items for sale. Clicking the Order link sends a request to the server via Ajax to lock the item. You will see the details of the page in Section 8.10.

8.3.2 Database Design

The second step of high-level design is to nail down the database schema. After researching the requirements of the project, the group decides to include the following three data tables in the design.

TBL_YARDSALE for storing information of yard sale events (e.g., location and time)

TBL_ITEM for storing items for sale

TBL_TRANSACTION for storing information about the buyers

The design of TBL_YARDSALE is shown in Table 8.3.1. Each row of TBL_YARDSALE stores the information of one sale event, e.g., a unique identifier, street address, and open and close time. The unique ID is the primary key of the table. It is a sequence of 10 natural numbers (each is less than 128). The unique ID number is randomly generated when a new record of a sale event is inserted into database.

The design of TBL_ITEM is presented in Table 8.3.2. The table contains the information of items for sale. The column named SALEID is a foreign key. Each item can be locked for 20 minutes by any buyer. LASTLOCKTIME represents the last timestamp for which the item is locked, and TRANSACTIONTOKEN identifies the buyer who is the current lock owner. The thumbnail image of the item is saved as a BLOB object.

As shown in Table 8.3.3, TBL_TRANSACTION stores information about transactions. Similarly, its primary key is a transaction token that consists of 10 natural numbers. Each record of TBL_TRANSACTION contains information of the name of the buyer, credit card number, and total purchase amount.

Table 8.3.1 Design of TBL_YARDSALE

Data Column Data Type Description
ID VARCHAR(40) Identity.Concatenation of 10 numbers (each <128). Primary key.
STREETADDR VARCHAR(30) Street address.
CITY VARCHAR(20) City name.
STATE CHAR(2) 2-letter U.S.state name.
ZIPCODE VARCHAR(10) 5-digit or 9-digit ZIP code.
FNAME_HOST VARCHAR(20) First name of the seller.
LNAME_HOST VARCHAR(20) Last name of the seller.
SSN CHAR(9) 9-digit social security number.
OPENTIME TIME Open time of the sale event.
CLOSETIME TIME Close time of the sale event.
SALEDATE DATE Date of the sale event.
DESCRIPTION VARCHAR(200) Any additional comments by the seller.

8.4 Milestone 1: Create a Web Project and Database with NetBeans

 

After finishing the high-level design, your next step is to finish the detailed design and implementation of each page in the project. First of all, you will use NetBeans to establish a Visual Web Pack project and the corresponding background database. NetBeans is one of the most popular open-source development tools for Java, and Visual Web Pack is an add-on to NetBeans that allows developers to build rapid prototypes of web applications with the assistance of server control techniques.

In this section, we will first give an overview of the technical details. Then you will have hands-on practice. The complete implementation of Milestone1, named MileStone1.zip, is available on this book's website.

In general, there are two ways of establishing a relational database with NetBeans: (1) use the JavaDB tool embedded in NetBeans, and add each table and define the relationship manually; and (2) create a database directly by using a SQL script. In the BigPeachYardSaleExpress project, approach 2 is selected for its simplicity and portability.

Table 8.3.2 Design of TBL_ITEM

Data Column Data Type Description
ID VARCHAR(40) Identity of the item.Primary key.
SALEID VARCHAR(40) Identity of the corresponding sale event. Foreign key.
PRICE DECIMAL(7) Price of the item.
DESCRIPTION VARCHAR(200) Additional comments by the seller.
KEYWORDS VARCHAR(30) Keywords for searching.
IMAGE BLOB Thumbnail image of the item.
STATUS INTEGER Integer code representing the status of the item.
LASTLOCKTIME TIMESTAMP Time when the item is last locked.
TRANSACTIONTOKEN VARCHAR(40) Current owner of the lock.Foreign key.

Table 8.3.3 Design of TBL_TRANSACTION

Data Column Data Type Description
TRANSACTIONTOKEN VARCHAR(40) Identity of the transaction.
FNAME_BUYER VARCHAR(20) First name of the buyer.
LNAME_BUYER VARCHAR(20) Last name of the buyer.
CARDNUMBER VARCHAR(15) Credit card number used for the transaction.
TOTALAMOUNT DECIMAL(7) Total amount of purchase.

Listing 8.4.1 displays the complete SQL script for establishing the database. The script has three parts. The first part adds a database user and grants the access rights. Part 1.1 calls a system procedure, SYSCS_SETDATABASE_PROPERTY, to add a user called derby.user.bigpeach and the password of the user is convenience. Then it adds the new account as a full-access user. Part 2 of the script is used to drop all existing tables in case the script is executed to wipe out the contents of the old database and recreate a new blank one. Part 3 uses the CREATE TABLE statement to create tables. It creates three tables: TBL_YARDSALE, TBL_TRANSACTIONS, and TBL_ITEM. Finally, foreign keys are defined using the ALTER TABLE statement to add constraints. TBL_ITEM has two foreign keys, one for SaleID and the other on TransactionToken.

images

images

Listing 8.4.1

SQL Script to Initialize the Database

Now the logic of the SQL script is clear. The next step is to explore how to create a Visual Web Pack project. Doing so is illustrated in the hands-on practice.

Hands-On Practice

 

In the following, you will create the BigPeachYardSaleExpress project and its database via hands-on practice. Please follow the instructions step by step. It is assumed that you have at least NetBeans 6.0.1. You should have the complete edition of NetBeans installed because it is bundled with Sun Application Server (code name GlassFish) and Visual Web Pack (code name Woodstock).

1. Launch NetBeans 6.0.1. Click the File menu, and then click New Project. A dialog will pop up. In the Categories box, select Web, and then in the Projects select Web Application as shown in Figure 8.4.1. Click the Next button.

images

Figure 8.4.1

Creation of BigPeach YardSaleExpress

images

Figure 8.4.2

Project Settings of Big-PeachYardSaleExpress

2. The second step is to set up the properties of the project. First, enter “BigPeachYardSaleExpress” as the name of the project. Click the Browse button to specify the location of the project. Then select GlassFish V2 (Sun Java Application Server) as the web server, and choose Java EE 5 as the Java EE version. Detailed settings are shown in Figure 8.4.2. Click Next to proceed to the next step.

3. In the third step (Frameworks), select the Visual Web JavaServer Faces framework and then click the Finish button. Then the project is successfully created.

images

Figure 8.4.3

Add DBScripts Folder

images

Figure 8.4.4

Create initDB.sql file

4. The fourth step is to create a folder in which to place the SQL script file. As shown in Figure 8.4.3, on the left-hand side of the NetBeans window, there is a project pane with three tabs: Projects, Files, and Services. The Projects tab displays the structure of the project. The Files tab displays the file folders of the project, and the Services tab displays the run-time servers (such as the web server and the database server) that support the project. Click the Files tab, and then right-click the root node (i.e., the project name BigPeachYardSaleExpress), select New, and then choose Folder. Name the new folder DBScripts and click Finish to add the folder.

5. The next step is to create the SQL script file. Right-click the DBScripts folder, select New, and then choose Empty File (as shown in Figure 8.4.4). Name the file initDB.sql. Enter the code in Listing 8.4.1 into initDB.sql.

images

Figure 8.4.5

Create the bigpeachdb Database

images

Figure 8.4.6

Run initDB.sql

6. Click the Tools menu of NetBeans, select Java DB Database, and then choose Create Database (as shown in Figure 8.4.5). A dialog will pop up to ask for the database name, username, and password. Use bigpeachdb as the database name, and the username and password should be bigpeach and convenience, respectively.

7. Now go back to the editor window of initDB.sql. Click the Run SQL File button (the one circled in Figure 8.4.6) on the tool bar or press Ctrl+Shift+E to run the initDB.sql file. The system will ask you to specify which database connection to use. Click the dropdown selection box (as shown in Figure 8.4.6), and select the big-peachdb that you have just created. The first execution will pop up several error messages reporting attempts to delete nonexistent tables. You can ignore the error messages. Running it a second time should result in no errors.

8. The last step is to verify that the database has been initiated. Click the Services tab, extract the bigpeachdb node, and then extract node tables; you should be able to see the three data tables already created. If the database is not connected yet, right-click the bigpeachdb node and select connect. A dialog will pop up to ask you for the username and password. Enter bigpeach as the username and convenience as the password. Once the connection is established, you can examine the table structure and contents of the database. Sometimes, NetBeans could not automatically refresh the database structure. In this case, you must go to the Tools menu, Java DB Database option, and select to stop and restart the database for updates.

8.5 Milestone 2: Portal Page and Cascading Style Sheet

 

This section constructs the first web page of the project, i.e., the portal page of BigPeachYardSaleExpress.com. It redirects buyers and sellers to buyer.jsp and seller.jsp, respectively. The structure of the portal page is simple: a header (ad banner) at the top and a body consisting of two hyperlinks for redirection. In this section you will be exposed to many useful techniques, e.g., the Cascading Style Sheet, page creation and layout using Visual Web Pack, manual layout using HTML table, orchestration of high-level page navigation, and the creation and reuse of Page Fragment.

8.5.1 Page Navigation

One great feature provided by Visual Web Pack is a tool called page navigation. Using page navigation, developers can define high-level architecture of a web application, e.g., which component of a web page can lead to another page and under which condition(s). The specification can be automatically mapped to the source code generated by the framework. In the following, you will first create Page1.jsp (the starting page of the project), then introduce two hyperlinks into the page, and finally redirect these two links to two other pages in the project.

Hands-On Practice

 

1. Make sure that the project BigPeachYardSaleExpress is open.

2. Click the Project tab of the project pane, extract the Web Pages node, and double-click Page1.jsp. Once the page is opened, the properties of the page (and its controls) are displayed on the right side of the NetBeans window, as shown in Figure 8.5.1. You can adjust the properties (also called attributes) of a web page and its controls by directly modifying the source code of the JSP page. To directly modify the source code, click the JSP tag of the main window of NetBeans. By default, the main window is in the Design mode, which allows you to view the visual design of a page. The JSP window allows you to directly edit the source code.

images

Figure 8.5.1

Setting the Page Layout

3. On the right side of the screen, go through the list of properties of Page1.jsp. Change the Page Layout property to Flow Layout (as shown in Figure 8.5.1). Flow layout allows arranging position of a web control relative to that of its owner control or siblings. The JavaServer Faces (JSF) framework will automatically arrange the layout of controls in a container when its layout is flow layout. To achieve similar effects, you can also use HTML table, which will be introduced in later sections.

4. Locate the Palette window above the Properties window (at the right side of the NetBeans window), as shown in Figure 8.5.2. If you cannot find it, click the Window menu of NetBeans and select Palette. The Palette window displays all server controls available in Visual Web Pack.

5. In the Palette window, find the Layout category, and drag and drop a Page Fragment control into the page. Click the Create Fragment button and create a new fragment called Header. A page fragment can be embedded into multiple web pages. It is an ideal tool for placing advertisement banners into each page of the project. You will edit the contents of the page fragment later. This step is shown in Figure 8.5.2.

6. In the Palette window, find the Basic category, and drag and drop two hyperlinks into the page. Set the id properties of the two hyperlinks to hyperlinkBuyer and hyperlinkSeller, respectively. Set the text property of the two links to Buyer and Seller correspondingly.

images

Figure 8.5.2

Drag and Drop a Page Fragment

7. The last step in this stage is to create the page navigation design. In the editor window for Page1.jsp, right-click and then select Page Navigation. The navigation scheme of the project will be displayed, as shown in Figure 8.5.3. Currently there is one page (Page1.jsp) in the design. Right-click anywhere in the design, and select New File. A dialog will show up to allow you to choose file types. Click JavaServer Faces as the category and then select Visual Web JSF Page as the file type, as shown in Figure 8.5.3. Then click the Next button and name the new page Buyer. NetBeans may jump to the new Buyer.jsp; you can click the faces-config.xml tab to go back to the page navigation design. Similarly, create a new page named Seller. Single-click the Page 1 node, and you will see the two links that you created in step 6. Drag an arrow line from hyperlinkBuyer to the Buyer.jsp page, and drag another arrow link from hyper-linkSeller to the Seller.jsp page. Later, you will see that the URL properties of the two hyperlinks are automatically set. Refer to Figure 8.5.3 for details of this step.

8. Press F11 to compile the project, and then press F6 to run the project. Click the buyer and seller links to verify that the browser is redirected to the right place.

images

Figure 8.5.3

Page Navigation

images

Figure 8.5.4

Structure of Page Fragment

8.5.2 Layout of Header Fragment by Using HTML Table

Next you will set up the layout of the header fragment. You will experiment with the use of HTML table. Although not as convenient as the drag and drop of visual controls in Visual Web Pack, HTML table gives you more freedom in expressing sophisticated designs. The structure of the page fragment is given in Figure 8.5.4.

The width of the whole page fragment will be 1000 pixels, which is also the width of all visible content of the page. The header consists of two parts: a logo of BigPeachYardSaleExpress.com and a dynamic banner. The structure is implemented by an HTML table that consists of one row. The row contains two cells, one with width 250px and one with width 750px. The height of both cells is 100px. The background color of the first cell is light yellow, and the second cell is in light blue.

Hands-On Practice

1. Extract the Web Pages node in the project pane, and then doubleclick the Header.jspf node in the project pane.

2. Click the JSP tab of the editor because you are going to directly set the contents of the JSP file, as shown in Figure 8.5.5.

3. Change the width from 400px to 1000px, and change the height from 200px to 100px.

4. Insert the following (Listing 8.5.1) as the contents of f:subview (i.e., embed Listing 8.5.1 between lines <f:subview> and </f:subview> in Header.jspf). Clearly, the inserted item is a table that contains one table row. The table row has two cells, one for displaying the BigPeachYardSaleExpress logo and the other for displaying dynamic advertisement. Note the setting of background color.

5. Run the project by pressing F6; the header should look like Figure 8.5.4.

images

Figure 8.5.5

JSP Contents of Header.jspf

Listing 8.5.1

Contents of Header.jspf

images

images

Figure 8.5.6

Layout of Page1.jsp

Listing 8.5.2

Cascading Style Classes Defined for Page.jsp

images

8.5.3 Refine Layout and CSS of the Portal Page

The next task is to reset the layout of the portal page by using HTML table. The planned layout is shown in Figure 8.5.6. The page consists of a table of three rows. The first row contains the header fragment; the second row provides a vertical space of 100 pixels; and the third row contains two cells, both of which contain a hyperlink.

Instead of manually defining the style of elements in the page, a designer can use a Cascading Style Sheet (CSS). Listing 8.5.2 displays the definition of two style classes: .MainTable and .PortalLink. The .Maintable class defines the background color and border style of the main table in the portal page.

The .PortalLink class defines the border style and font size of the hyperlinks. The A:hover class specifies that when a mouse hovers over a hyperlink, its background color will be changed.

Hands-On Practice

 

1. Extract the Web pages node in the project pane, find the resources node, and then double-click the stylesheet.css node. Append the code in Listing 8.5.2 at the end of the file.An alternative way is to manually add the style classes by using the CSS editor provided in NetBeans.

2. NetBeans sometimes does not automatically redeploy the CSS on the server. Click the Services tab in the project pane, select the HTTP server (GlassFish2 by default), and then right-click and select restart to let the CSS take effect.

3. Click the Projects tab again to go back to project structure.

4. Open Page1.jsp, and click the Design tab to view the visual design. Select the two hyperlink controls and set their property styleClass to PortalLink, as shown in Figure 8.5.7. You must ensure that PortalLink class appears in the Available Classes list first. If it does not exist, you must recompile the project and restart the ClassFish2 Server (in the Services tab of the project pane) to ensure that the CSS is updated. Sometimes restarting NetBeans may help. You must click the “>” button in the style class selection dialog to make PortalLink appear in the Selected Classes list.

images

Figure 8.5.7

Setting the Style Class of Hyperlinks

Listing 8.5.3

Table Layout of Page1.jsp

images

5. Now open Header.jspf by clicking the corresponding node in the Projects tab. Click the JSP button of the editor, and you will modify the contents of Header.jspf. Enter the code of Listing 8.5.3 into the webuijsf:form element (i.e., replace the code between the <webuijsf:form> and </webuijsf:form> tags with the contents of Listing 8.5.3).

6. Press F6 to run the project; the portal page should look like Figure 8.5.8.

images

Figure 8.5.8

Initial Portal Page without Dynamic Ad Banner

8.6 Milestone 3: Seller Page and JavaServer Faces (JSF)

 

This section presents the exciting JavaServer Faces (JSF) technology. You will use JSF to build Seller.jsp for uploading information for a yard sale event. Various techniques for manipulating databases, e.g., JDBC and JSF data table, will be addressed.

The Seller.jsp page creates a yard sale event and inserts a new record into the TBL_YARDSALE table. Each yard sale event has a unique ID (identifier), which is a sequence of 10 three-digit numbers. The resulting state space of ID is about 12810. According to the theory of statistics, there could be hardly any collision after randomly generating 1010 IDs. So in practice, you can feel safe in randomly generating an ID for a new record.

Listing 8.6.1 presents the source code of ID.java. It defines a collection of essential functions provided by the ID class. The ID class has one static attribute named valueLength, which defines the number of natural numbers in one ID. Because valueLength is defined as a constant integer 10, it indicates that an ID consists of 10 natural numbers. The actual values of these natural numbers are stored in the array named value. The constructor of ID initializes the value array by using the Random class provided by Java API. The value of each random number ranges between 0 and 127; hence, each number can be represented using 1 byte. The toString() method dumps the contents of an ID. The equals() method checks whether two IDs are equal by looking at each number in the array value. Finally, the class is defined to implement the Serializable interface so that it can be stored as a binary array in database.

To model the TBL_YARDSALE table, a class named YardSale is defined, as shown in Listing 8.6.2. The YardSale class has a list of data members to model each column of TBL_YARDSALE; e.g., the fName is used to model the first name of host, and streetAddr for the street address. When a YardSale object is created, its id is instantiated using the random number generation as presented in Listing 8.6.1. The class provides a list of accessor functions to retrieve the values of its data members (at the end of Listing 8.6.2), as well as one mutator function for setting its data members. The most important function of the class is the persist() function, which simulates the Java Persist API. It uses JDBC to access the database and inserts a new record into the database. The persist() function, calls the getDBConnection() function provided by a Utility class, which is defined in Listing 8.6.3. The getDBConnection() calls the DriverManager to get a database connection (by supplying the connection string, database user account, and the password).

Listing 8.6.1

Source Code of ID.java

images

Listing 8.6.2

Source Code of YardSale.java

images

images

images

Hands-On Practice

 

1. The first step is to incorporate Utility.java into the project. In the project pane, extract the project node BigPeachYardSaleExpress, right-click Source package, select New, and then Java Package, and create a package named YSEModel.

Listing 8.6.3

Source Code of Utility.java

images

2. Right-click YSEModel in the project pane, select New and then choose Java Class. Name the new class ID. Enter the code (ID.java) in Listing 8.6.1. Press F11 to compile the code.

3. Right-click YSEModel in the project pane, select New and then choose Java Class. Name the new class Utility. Enter the code in Listing 8.6.3. You might have to modify the code of getConnection() in your implementation for setting up the right connection string on the basis of the configuration of the database on your system. To get the right connection string, click the Services tab in the project pane, extract the databases node, select and right-click on the database you are using, and then click Properties. A dialog will pop up. Select and copy the value of a property called Database URL, and then insert it into the code of Utility.java (the line right below conn = DriverManager.getConnection). Press F11 to compile the code.

4. Similarly, create a new Java Class called YardSale and enter the code (YardSale.java) in Listing 8.6.2. Press F11 to compile.

5. Up to now, all classes for the logical model have been defined. In the project pane, extract the Web Pages node and double-click Seller.jsp to open it. You will first drag and drop server controls into the page and then use HTML table to set up the layout. Click the Design tab to make sure that the editor is in visual editing mode. You should see the control palette on the right-hand side of the window. Otherwise, click the Window menu and select Palette to make sure that the palette shows up.

6. Click anywhere inside the editor and make sure that the page itself is selected. Find Layout in the property list, and set it to Flow Layout so that later you can use HTML table to position controls.

7. Drag and drop a Layout Panel from the Layout category to the visual editor. Enlarge it enough to occupy two-thirds of the visual editor. Click the ellipsis button of the style property and set its background to light yellow so that it is visually identifiable in the visual editor.

8. Set the panelLayout property of the Layout Panel control to Grid Layout so that within the panel you can freely adjust the position of controls.

9. Drag and drop label and textbox controls as shown in Figure 8.6.1. The complete list of controls (with labels omitted) is shown in Table 8.6.1.

images

Figure 8.6.1

Layout Design of Seller.jsp

Table 8.6.1 Server Controls in Seller.jsp.

Name Control Type Corresponding Label
txtStreetAddress Text field Street address
txtCity Text field City
txtState Text field State
txtZip Text field ZIP code
txtFName Text field First name of host
txtLName Text field Last name of host
txtSSN Text field Social Security number
dropDownOpenTime Drop-down list Open time
dropDownCloseTime Drop-down list Close time
calendar Calendar
txtDescription Text area Description (max.200 chars)
messageGroup1 Message group
btnSubmit Button

10. For each text field, drop-down list, calendar, and text area control in Figure 8.6.1, in its property list, check the Required checkbox. When the page is submitted, these controls cannot be empty.

11. Press the Ctrl and Shift keys down simultaneously, and drag the Street Address label into the text box on the right. This is to set the for property of the label so that the label can display system-related messages for the text box. For example, it will display an asterisk (*) when a user forgets to enter the text into the corresponding server control that the label is bound to. You can also directly set up the for property in the property list of the Street Address label. Repeat the same procedure for all other labels.

12. Next you can set up the default items of the two drop-down lists. Right-click the first drop-down list and select Configure Default Options. A dialog will pop up. Delete the existing items in the list, and create entries as shown in Figure 8.6.2. You can set up entries from 6 AM to 6 PM. Repeat it for the second drop-down list. For the value part, you need to use the hh:mm:ss format. It is required by the parser of the java.sql.Time class when the value is saved to the database.

images

Figure

Initial Contents of DropDown Lists

13. Drag and drop a page fragment from Layout and set its content as Header.jspf.

14. The next task is to insert a session variable into the page. A session variable is used to maintain data during a user session. For example, it is desirable for the system to remember the ID of the seller after visiting the Seller.jsp page, because later the PostItem.jsp page needs it when inserting new records about items for sale.

Make sure that Seller.jsp is selected; double-click the SessionBean1 node (as shown in Figure 8.6.3). The contents of the session bean class will be displayed in the editor. Right after the last import statement in the file, append import YSEModel.*; and then right before the init() function, insert the following lines of code. The purpose of this code snippet is to declare a property named saleID, which will be set by the Seller.jsp page and then used by PostItem.jsp. Press F11 to compile.

images

Figure 8.6.3

Add Property into Session

images

15. Then you will go on to set up the layout of the Seller.jsp page. Click the Seller.jsp tab in the editor to return to editing the page. Click the JSP tab. The NetBeans editor allows you to collapse and extract the code by clicking the “+” and “” buttons on the left ruler of the editor. Collapse the nodes for header fragment and the panel layout panel. Enter the code of Listing 8.6.4 right after the line <webui-jsf:form binding=“#{Seller.form1}” id=“form1”> and right-click in the editor and select Reformat Code. NetBeans will automatically set up the proper indentation.

16. Now you need to move the header fragment into the first row of the main table in Listing 8.6.4. Select the header fragment code (it is a div in the code, which contains Header.jspf). It is recommended to collapse the whole code snippet of header fragment into one line. Press Ctrl+X to remove the header fragment code, and paste it right below the comment <!--HEADER GOES HERE! --> (by pressing Ctrl+V). Similarly, paste the code snippet of the whole panel layout control right after the comment <!--LAYOUT PANEL GOES HERE! -->.

Listing 8.6.4

HTML Table Layout of Seller.jsp

images

17. Then you will handle many details related to the style of server controls. Go to the div code for the page fragment. Remove a string that defines the style property, because its size and absolute position are no longer needed. Click the Design tab to go back to visual editor, and make sure that the layoutPanel is selected. Click Style in its property list; a dialog will pop up. Click Position (on the left) and make sure that Relative mode of position is selected. Also set the To p and Left to be 0px. Doing so ensures that layoutPanel stays in the table cell. Now press F11 to compile the whole project and press F6 to run it. Click the Seller link to jump to the Seller page. The layout should resemble Figure 8.6.1.

18. The last task is to finish configuring the Submit button. Go back to the visual editor for Seller.jsp. Double-click the Submit button and enter the code in Listing 8.6.5 into the event handling function. This code snippet simply calls the setValues() method of YardSale and then calls the persist() method to insert a new record of a yard sale event into the database. Right-click in the editor and select Fix Imports. While fixing the imports for Time and Date classes, there could be multiple candidates. Make sure that java.sql.Time and java.sql.Date are selected. Then press F11 to compile the project.

Listing 8.6.5

Implementation of the Submit Button

images

19. Now the Seller.jsp page is completed. Press F6 to run the project. Go to Seller.jsp by clicking the Seller link in the portal page. Fill out some sample data and click the Submit button.

20. Click the Services tab in the project pane. Extract the database node (if the node cannot be extracted, you need to right-click and select Connect first), and then drill down to TBL_YARDSALE. Right-click and select View Table Contents. You will see a new record inserted into the data table.

8.7 Milestone 4: Upload Images and Java Servlet

 

Your next task is to build a page for uploading items for sale. In this section, you will learn to use a JSF server control called data table. You will also use a Java Servlet to retrieve images from the database. As usual, you will be introduced to the basic design idea first. Then you will proceed with hands-on experience.

In BigPeachYardSaleExpress, the thumbnail images of items for sale are stored in the database as a binary array. A Java Servlet called FetchImage is used to retrieve an image from the database and write the byte array into the output stream when HTML responses are generated. The source code of FetchImage is shown in Listing 8.7.1. The servlet accepts two parameters: (1) ID, the identifier of the item, and (2) maxWidth, the maximum image width to display. The image saved in the database can have higher resolution than the one being displayed on the web page. The servlet can scale an image to satisfy the needs of the page.

As shown in Listing 8.7.1, function massageImage() scales the image. The basic idea is to call Graphics2D.scale() to scale the canvas that the image is being drawn on. Then Graphics2D.drawImage() is invoked to draw the image that is scaled to the canvas. The result is returned as a byte array.

Function retrieveImage() retrieves the binary data of the image for an item for sale. It calls massageImage() to scale the image to maxWidth and returns the data. The SQL statement is constructed on the fly, and JDBC is used to execute the SQL statement.

Function processRequest() serves incoming HTTP requests. No matter whether the request is of type GET or POST, the value of the parameters can be easily retrieved using Request.getParameter(). processRequest() gets the value of two parameters, ID and maxWidth, calls retrieveImage() to get the byte array of the desired image, and then writes the byte array as output. Before the output is written, the content type of the HTTP response is set as img/jpeg by the program.

The FetchImage servlet is called by the PostItem.jsp page. Next you will study the implementation of PostItem.jsp. The visual layout of the page is shown in Figure 8.7.1. As shown in the figure, a sale event organizer can upload the price, a brief description, keywords, and a JPEG image for each item for sale. There is a data table control at the bottom of the page. It can be bound to a data source. Manipulation of data can be simplified by using the default functions provided by the data table control; hence, a programmer does not have to directly write the SQL statement. This feature can greatly simplify the implementation of many database application scenarios.

As shown in Figure 8.7.1, once the Add button is clicked, a new record about the item should be inserted into the database. Because of the use of the data table control, the addition of the new item can be simplified. Listing 8.7.2 presents the handling of the Add button. The function first calls the appendRow() function, which is supplied by the data provider associated with the data table. appendRow() returns a row key that uniquely identifies each row in the data table. Then the new row has the focus of the data table, where the subsequent database operations will be applied to that row. The rest of the code is to set up the values for each column of the new record, correspondingly.

Listing 8.7.1

Source Code of Fetch Image.java

images

images

images

images

Figure 8.7.1

Layout of PostItem.jsp

Pay special attention to how the function handles the upload of the image file. By calling function getUploadFile().getBytes(), you can easily get the byte array of the image. Then by calling setValue() of the data provider, you can set the value of the column named IMAGE. Finally, commitChanges() is called to write the change to the database.

Listing 8.7.3 presents the handling of the Delete button in Figure 8.7.1. The function first gets the row key of the current row. Then it uses a JDBC PreparedStatement to execute a DELETE statement. Finally, it invokes the refresh() function of the data provider (which is associated with the data table) to update the contents of the data table. After getting a clear understanding of the back-end code of PostItem.jsp, you can now proceed to the hands-on experience.

Hands-On Practice

1. The first step is to build the Java Servlet that fetches and outputs a JPEG image from database. Right-click the BigPeachYardSaleEx-press node in the project pane, select New, and then choose to create a Servlet. Name the new servlet FetchImage. Enter the code in Listing 8.7.1. [Actually, you have to type only the first three methods: retrieveImage(), massageImage(), and processRequest()]. Press F11 to make sure that the project compiles.

Listing 8.7.2

Source Code of the Add Button Handler

images

Listing 8.7.3

Source Code of the Delete Button Handler

images

2. The next task is to create PostItem.jsp via the use of Visual Web Pack editor. Right-click the BigPeachYardSaleExpress node in the project pane, select New, and then choose Visual We b JSF Page. Name the new page PostItem. Use all default configurations in the Create New Page dialog, and click the Finish button. Go to the property list window on the right-hand side, and set Page Layout to Flow Layout.

Table 8.7.1 Controls in PostItems.jsp

Name Control Type Corresponding Label
txtPrice Text field Price
txtDescription Text field Description
txtKeywords Text field Keywords
fileUpload1 File upload Image
messageGroup Text field Message group
btnAdd Text field Add
table1 Table Table

3. Drag and drop a Layout Panel to the page, and set its panelLayout property to Grid Layout. Set the style property so that the background of the panel is light yellow. Adjust its size to that of the one in Figure 8.7.1.

4. Drag and drop the controls in Table 8.7.1 into the Layout Panel as shown in Figure 8.7.1.

5. Next you must set the data source provider for the data table. Click the Services tab of the project pane, and then extract the bigpeach node and the tables node. If the bigpeach database is not currently connected, right-click the node and select connect and then enter the username bigpeach and password convenience. Select TBL_ITEM and drag it to the title bar of the data table in Pos-tItem.jsp. You should be able to see that the data table now has the structure of TBL_ITEM.

6. Clearly, it is not necessary to have so many columns in the data table. The next task is to select only the columns related to the page. Right-click the data table and select Table Layout. Move unneeded columns to the left and leave only the following four columns in the list (the pane on the right):

TBL_ITEM.ID

TBL_ITEM.PRICE

TBL_ITEM.DESCRIPTION

TBL_ITEM.KEYWORDS

images

Figure 8.7.2

Setting Table Layout

Next, you will create one column for deleting items and one column for displaying the thumbnail images of items. Click the New button on the right side of the dialog, and create a column button, as shown on the left side of Figure 8.7.2 (set its Header Text as Delete, Component Type as Button, and its Value Expression as Delete). The Delete button, once clicked, will delete the current item from database. Finally, click the New button, and create an ImageHyperlink column as shown on the right side of Figure 8.7.1 (set its Header Text as Image, the Component Type as ImageHyperLink, and its Value Expression as aaa). You will later set up the URL and ImageURL property of the column and remove aaa as the Value Expression.

7. Now click any cell of the Image column and select ImageHyperlink (so that the property pane displays the properties of imageHyper-link1, as shown in Figure 8.7.3). Set the imageURL property to the following:

images

This code snippet calls the FetchImage servlet for retrieving the image of the item. Notice that #{} encloses a Java expression that is to be evaluated when generating each row in the data table. Clearly, it retrieves the corresponding ID of the item displayed in each row. Maximum width of the image is set to 100 pixels.

images

Figure 8.7.3

Setting the URL of a Hyperlink in the Table

Similarly, set the URL property of the image link to the following. This time, a new page will be popped up for displaying the image in greater detail because maxWidth is set to 800px.

images

8. Click to select the ImageLink again, and then remove aaa in its Text property. Set the value of the property as an empty string.

9. Implement the Add button. Double-click the Add button in the visual editor, and include the code given in Listing 8.7.2 in the corresponding handler function (only the function body). Right-click in the editor and select fix imports, and then press F11 to compile. If the compiler complains about a function called getSessionBean1(), insert the following into the class body of PostItem.java.

images

Double-click any of the Delete buttons in the table, and enter the code given in Listing 8.7.3 (only the function body). Right-click and select Fix Imports, and then press F11 to compile.

The database programming has not been completed yet. The data provider of the data table in PostItem.jsp simply lists all available items stored in the TBL_ITEM table. You must append a WHERE clause to the SQL query of the data provider. In Visual We b Pack, database service is provided in two layers: data provider and cache row set. The cache row set underneath the data provider manages SQL queries.

images

Figure 8.7.4

Setting Row Set

As shown in Figure 8.7.4, double-click PostItem.jsp in the project pane to make sure that it is selected. Underneath the project pane, there is a pane called Navigator (as shown on the left-hand side of Figure 8.7.4). Extract the SessionBean1 node and double-click tbl_ItemRowSet. The SQL editor window will show up (as shown on the right side of Figure 8.7.4). Append a new line into the query as follows (right after the FROM clause), and then close the SQL editor window and save the query. Clearly, the WHERE clause guarantees that only items related to the current sale event will be displayed in the data table. The ? represents a parameter passed to the SQL query.

images

You now need to pass the value of the parameter to the query, i.e., the saleID stored in the session variable (which is set by Seller.jsp when creating a new yard sale event). Double-click PostItem.jsp in the project pane, click the Java tab of the editor to edit its Java code, and then locate a function named init(). The init() function is responsible for initializing the values of controls when the page is loaded but before it is rendered to the web browser. Append the code in Listing 8.7.4 after the line // TODO - add your own initialization code here. The code uses the setString() function provided by the row set object to set the value of the first (and the only) SQL parameter. You must first convert the saleID from ID to String, because the sale ID is saved as a string in the database.

Listing 8.7.4

Source Code of the init() Function of PostItem.jsp

images

12. The last job is to hook the PostItem.jsp to the project. In the project pane, double-click to open Page1.jsp. Click the Design tab. Then right-click in the editor and select Page Navigation. The project configuration file called faces-config.xml will be displayed. Depending on the version of your NetBeans, you might find that PostItem.jsp is not contained in the page navigation design. If so, you need to click a button called Reset Page Layout to bring in PostItem.jsp. The Reset Page Layout button is located on the toolbar of the editor (by default, the buttons on the toolbar are Page Flow, XML, a drop-down list for setting scope filter, and the Reset Page Layout button). Click and extract the Seller.jsp node in the navigation scheme, and then drag one arrow from its Submit button to PostItem.jsp in the navigation diagram. Press F11 to compile the project.

13. Press F6 to run the project. Click the Seller link to enter Seller.jsp. Fill out sample data of the sales event and click the Submit button. Now your browser should jump to PostItem.jsp. Fill out the data of a sample item (two sample JPEG images are available in the Resources/SaleItemPictures folder on this book's website) and click Add. A new row about the item with the item's thumbnail image will show up in the data table control.

8.8 Milestone 5: Dynamic Ad Banner and Ajax

 

This section introduces the use of Ajax to enrich traditional web applications. One nice example is the creation of a dynamic advertisement banner. The banner will be able to periodically download advertisement snippets from the server. The banner can also execute the JavaScript code accompanying the advertisement graphics. New advertisements can be uploaded to the server and be immediately available without restarting the web server.

To create the dynamic banner, you must go through three steps. (1) You will modify the Header.jspf fragment so that asynchronous calls will be invoked periodically for downloading advertisement content. (2) You will create a Java Servlet to respond to the asynchronous calls. The servlet will randomly retrieve an advertisement (HTML and JavaScript snippet) for each request. (3) You will create several sample advertisement snippets by using HTML and the Dojo animation framework.

You will first examine some of the design issues of the aforementioned steps. Then you will have hands-on experience turning the dynamic ad banner into reality.

Modification on Header.jspf. Recall that the main structure of Header.jspf consists of one table that has two table cells. You will first place a DIV element named headerDIV into the second data cell. The headerDIV is used to display the advertisement. At run time, a piece of JavaScript code will periodically execute XMLHttpRequest (XHR) to retrieve banner contents from server. Listing 8.8.1 displays the XHR code and the new HTML layout of the header fragment.

As shown in Listing 8.8.1, when the header fragment is loaded, the JavaScript code calls setTimeout() to periodically invoke function getHeaderContents(), which is used to retrieve the advertisement. In getHeaderContents(), an instance of XMLHttpRequest object is created. Later, myCallBack() is hooked up to the response of XHR request. Then getHeaderContents() sends a request to a Java Servlet called getBanner (which will be explained later), using GET.

When data is returned, myCallBack() is invoked. It first checks the ready state of the XHR object. If it is 4 (successful), myCallBack() will replace the innerHTML contents of the headerDIV with the data returned. The returned data, normally, consists of a piece of HTML code. However, if necessary, it can contain a piece of JavaScript code to be executed. If both HTML and JavaScript exist in the returned data, they are separated using the phrase --HAS_SCRIPT--. The myCallBack() function can separate the two parts by searching for the string --HAS_SCRIPT--. Then by separating the returned data into two strings, myCallBack() gets the HTML content as the first part and the JavaScript snippet as the second part. To make the JavaScript snippet effective, eval() is used to to evaluate and execute the downloaded JavaScript snippet.

Listing 8.8.1

Source Code of Header.jspf

images

images

Servlet getAdBanner. Next, a Java Servlet named getAdBanner is created for retrieving an advertisement banner randomly from a given system folder. Listing 8.8.2 displays the source code of getAdBanner. The implementation of the servlet consists mainly of two methods: processRequest() and getFiles(), where getFiles() is used by processRequest() to retrieve the list of file names in a folder called /Resources/AdBanners. The getFiles() method first creates a File object to access the /Resources/AdBanners folder and then calls a list() function to get the list of file names within that folder. To get the full qualified file path, you must first obtain the real path of the /resources/AdBanners/ URI from the servlet's context. The list of results is finally packed in an ArrayList and returned to processRequest(). In the processRequest() method, a random number is generated to randomly decide which advertisement to show. Then the file content is read, concatenated, and sent back to the caller.

Listing 8.8.2

Source Code of the getAdBanner Servlet

images

images

Listing 8.8.3

Banner 1 Contents (banner1.txt)

images

Advertisement Samples. Finally, you will create two advertisement samples. Listing 8.8.3 displays a sample banner that consists of a JPEG image file. The subsequent listing displays a second banner that has a JPEG image file as its contents, but it is enhanced with a JavaScript code snippet. The JavaScript part defines a function called playit(), which calls the wipeIn() and wipeOut() functions provided by the dojo.fx package. The dojo.fx package is a part of the Dojo framework for displaying animation effects.

Hands-On Practice

 

1. The first task is to copy the Dojo framework into the project folder. Open the project folder. Create a folder named js inside the web folder. Copy the Dojo version 1.0.2 (a folder named dojo-release-1.0.2) into the js folder. The folder can be downloaded from the textbook website (Ch8/Resources/dojo-release-1.0.2/).

Listing 8.8.4

Banner 2 Contents (banner2.txt)

images

2. The next task is to modify Header.jspf. In the project pane, extract the Web Pages node, and double-click Header.jspf to edit it. Click the JSP tab to edit the source code. Enter the following code right after the first “<div ’>” statement in Header.jspf. It loads the Dojo framework for displaying animation effects. You can verify the correctness of your operation with Listing 8.8.1.

images

3. Enter the following code into the second <td> element of the HTML table. It is used to replace the original contents <h2>Dynamic Ads. Here!</h2>.

images

4. Click the Design tab, and drag and drop a Script component from the Advanced category of the server control palette. Then click the JSP tab. Enter the part of the code in Listing 8.8.1 that is between the line <webuijsf:script binding=“#{Header.script1}” id=”script1”> and </webuijsf:script>). Up to now, the contents of your Header.jspf should look exactly like the one in Listing 8.8.1.

5. The next task is to create the servlet for retrieving banner contents. Click the Project tab in the project pane, right-click BigPeachYard-SaleExpress, and select New and then Servlet. Name the new servlet getAdBanner.

6. Enter the function getFiles() in Listing 8.8.2 into getAdBanner.java.

7. Enter the function body of processRequest() in Listing 8.8.2 into getAdBanner.java (you need to remove the original contents generated by NetBeans first).

8. Right-click in the editor and select Format to beautify the code. Then right-click in the editor again, and select Fix Imports. Press F11 to compile the project. At this point, the programming for the advertisement banner is done.

9. The last job is to create the advertisement contents. Click the Files tab of the project pane, extract the BigPeachYardSaleExpress node, then the web node, and then the resources node. Right-click the resources node, select New, and then choose Folder. Create a folder called AdBanners, and similarly create a subfolder called Figures inside AdBanners.

10. Right-click AdBanners and select New and then choose Empty File. A dialog will pop up. Name the file adBanner1.txt. Enter the code in Listing 8.8.3 as its contents. The file should be placed under AdBanners instead of Figures.

11. Repeat the same procedure in step 10 and create a file named adBanner2.txt.

12. Start Windows Explorer and open the project folder of BigPeach-YardSaleExpress. Locate the subfolder web/resources/AdBanners/ Figures. Copy two files, Banner1.jpg and Banner2.jpg, into the Figures folder. The two JPEG files can be found on the textbook's website (in folder /Resources/adBannerPictures). These two figures are created using open-source tool GIMP2. You can also create similar figures. The size of the banner JPEG files must be 750 × 100 pixels.

13. Now press F11 to compile the project and then press F6 to run it. You should see that the header banner is refreshed every 2 seconds. The second advertisement comes with special wipe-in effects.

8.9 Milestone 6: Buyer Page and Dojo Framework

 

In this section, you will start the construction of Buyer.jsp by using pure Ajax. Most of the page is implemented as a plain HTML file that uses JavaScript to interact with the user. You will learn many interesting techniques such as the use of Dojo for setting up sophisticated layout of a web page. You will first examine the design of Buyer.jsp, then the layout of MapIDE.html (which is embedded in Buyer.jsp), and finally proceed with hands-on experiments.

Shown in Listing 8.9.1 is the main part of the Buyer.jsp page. Similar to other pages in the project, Buyer.jsp has two parts: the header banner and the main contents. To better streamline the logical structure design, you will move all Ajax-related contents into a file called MapIDE.html. Thus, in Buyer.jsp, an IFRAME is used as the container of MapIDE.html.

The map IDE (Integrated Design Environment) has a sophisticated user interface, as shown in Figure 8.9.1. Its left-hand side is a toolbox, which contains three sliding content panes: buyer information, shopping cart, and itinerary. Its right side is a map IDE environment, which allows users to perform online shopping operations directly on the map. The layout is implemented using various content pane controls provided in the Dojo framework, e.g., dijit.layout.LayoutContainer, SplitContainer, and AccordionPane.

Listing 8.9.2 displays the source code ofMapIDE.html. The general layout of MapIDE.html is derived from the mail example included in the dijit.demos package of Dojo. The title of the page is “Big Peach Map IDE”. The file relies on Dojo framework version 1.0.2, as shown by the first script block in the page. Next, the second script block loads various modules that are required for the Dojo controls used in the page, e.g., LayoutContainer, SplitContainer, ContentPane, and DateTextBox. A function called getDate() is used to initialize the text of the date pick box by using the current date of the client computer. The initialization is done via Dojo.addOnLoad(). The web page relies on a collection of predefined style files provided by the Dojo framework; e.g., the style of the main table uses the soria class provided by Dojo, as well as several other style classes defined in the mail.css file that is a part of the mail example in dijit.demos.

Listing 8.9.1

Main Contents of Buyer.jsp

images

images

Figure 8.9.1

GUI Design of Buyer Information Pane

Listing 8.9.2

Initial Contents (Buyer Info Only) of MapIDE.html

images

images

images

images

images

The layout is specified by a Dojo LayoutContainer, which consists of two parts. The left part is a Dojo SplitPane, which contains three AccordionPanes:Buyerinfo, ShoppingCart, and Itinerary. Each AccordionPane's content is presented using an HTML table, and each row of the table consists of two cells: the left cell is used for labels, and the right cell is used for control. As shown in Figure 8.9.1, the BuyerInfo pane consists of many different controls: text box, drop-down list, date pick box, etc. All Dojo controls are similar: each Dojo dijit control is a standard HTML input control, which has an additional tag named dojoType.

Pay special attention to the nice validation feature provided by Dojo. For example, regular expression is used for specifying the allowed text in the ZIP code textbox. There are two types of ZIP code: five digit and nine digit. The constraint is expressed using regular expression, where “d” stands for a digit and “{5}” denotes the occurrence of “d” for exactly five times. So ZIP code can be captured using a regular expression as below:

images

If a user types a string that does not conform to the regular expression format checker, the contents of invalidMessage will be displayed to inform the user about the format requirement. Dojo framework automatically handles the event triggering and the style setting of the textbox hints. Similarly, you can set the required attribute of a textbox to make sure that the textbox is not empty when the page is submitted.

At this moment, only the source code of the BuyerInfo pane is provided. The other two panes, i.e., the ShoppingCart and Itinerary panes, will be addressed in later sections.

Hands-On Practice

 

1. Double-click Buyer.jsp in the project pane, and click the JSP tab of the visual editor. Locate the following two lines:

images

2. Enter the code of Listing 8.9.1 between the preceding two lines.

3. In the project pane, right-click the Web pages node, select New and then choose HTML. Name the new file MapIDE.

4. Enter the code in Listing 8.9.2 into MapIDE.html.

5. Press F11 to compile the project. Then press F6 to run the project. Verify that the layout of Buyer.jsp looks like Figure 8.9.1.

6. You might notice that the header banner could occupy too much empty space. In this case, double-click the Header.jspf node in project pane, click the Design tab, and in the property list set the Height property to 100px.

8.10 Milestone 7: Map IDE and Google Maps

 

The next step is to implement a comprehensive map environment for online shopping. It is called Map IDE (Integrated Development Environment). In this section, you will be exposed to the Google Maps API. You will also further develop the understanding of server-side techniques via the creation of several Java Servlets. You will find that the asynchronous nature of Ajax via callback is rather different from traditional imperative programming. You will have opportunities working with JavaScript. When you finish the hands-on experience of this section, you will produce around 200 lines of JavaScript code.

You are going to enrich the current implementation of BigPeachYardSaleExpress with the following, as shown in Figure 8.10.1. A buyer can specify several search criteria (e.g., the desired shopping date and the maximum radius of the search). Once the Search button is clicked, BigPeachYardSaleExpress needs to display all applicable sale events on the Map IDE. The buyer can click on any event, which will bring another popup with the list of items for sale (the price, name, thumbnail image of the item, and one link for ordering the item). If a buyer is interested in some item, he or she simply clicks on the order link and the item is dropped into the shopping cart pane. The shopping cart pane will display the information of all ordered items and a total sum of the expenditure.

images

Figure 8.10.1

Map IDE and Shopping Cart

Algorithm of Searching Sale Events. Technically, the most challenging task is to search sale events by using buyers’ criteria. The search process is conducted in two steps:

(1) A request is sent to a Java Servlet named searchSale to retrieve a list of yard sale events that have the specified date and are located in the same state as the buyer. The results are concatenated and returned as a JSON array so that the information can be easily interpreted by the client side.

(2) Then the client-side JavaScript sends the address of each returned sale event to the Google Maps service for determining the driving distance from the buyer's home address. If the sale event satisfies the buyer-specified criteria, it is displayed on the Map IDE.

You might wonder: why not complete the evaluation of driving distance on the server side? Using the client side as an intermediate relay seems redundant and complex. The reason for this complex treatment is that the geocoding service provided by the Google Maps service (which is needed for calculating driving distance) must be invoked using designated JavaScript API at the client side. Thus, you must split the search process into two steps. In the following, you will examine the logic of the searchSale servlet first. Most of its source code is displayed in Listing 8.10.1.

As shown in Listing 8.10.1, the function of the searchSale servlet is to return a list of yard sale events that are located in a given state and organized on a given date. There are two major functions in Listing 8.10.1. Function processRequest() is used to process the query request. It relies on a second function, i.e., getSalesInJson(), to retrieve the information from the database. getSalesInJson() first establishes the SQL connection to the database and then constructs the SQL statement on the fly (notice its WHERE clause). The results are concatenated as a JSON array, which can be easily interpreted by client side JavaScript code. Listing 8.10.2 displays one sample JSON array that can be constructed by the servlet.

When the JSON array of candidate sale events is sent to the client side, a comprehensive set of JavaScript functions must be invoked to send requests to the Google Maps service (for getting the driving distance to each event from the home address of the user). When the map results arrive, each sale event will be examined. Those that are located within the specified radius will be added to Map IDE.

Listing 8.10.1

Source Code of searchSale.java

images

images

Listing 8.10.2

Sample JSON Array Constructed by searchSale.java

images

All JavaScript functions that are related to the Map IDE are collected in a file called MapOps.js. Listing 8.10.3 displays the contents of the file. To make sure that you will understand the JavaScript functions in later discussions, please go over the list of global variables first.

map: an instance of the Google Maps service.

Listing 8.10.3

Source Code of MapOps.js

images

images

images

images

images

images

geocoder: an instance of the wrapper class that invokes the geocod-ing service provided by Google Maps. The service is used for translating street addresses into geographic coordinates.

saleinfo: a JSON string that represents the information of a sale event. It can be easily converted to a JavaScript array.

arrSaleGeoPoints: a list of the geographic coordinates of sale events.

curIdx: current index. It is used by asynchronous functions to decide the progress of the processing of sale events.

arrSaleAddrs: a list of street addresses of sale events.

arrSaleID: a list of IDs of the sale events.

clientAddr: the home address of the buyer.

clientGeoPoint: the geographic coordinates of the buyer's home address.

arrDistances: a list of decimal numbers that represent the distance to each sale event from the buyer's home address.

buyerID: the ID of the buyer.

Listing 8.10.3 consists of many functions. You will examine each of them, following the order that they are invoked when BigPeachYardSaleExpess handles the Search button:

1. When a user clicks the Search button, getClientAddressAndStartFilter() is invoked. The function sets up and displays a marker for the user's home address on the Map IDE.

2. At the end of getClientAddressAndStartFilter(), function sendBuyerInfoForm() is called. The function relies on Dojo to handle XHR request, which saves coding efforts. The function sends the request to servlet searchSale. Then it specifies that once data arrives, it will assign the data to the global variable saleinfo and invoke startProcessSaleAddrs() for processing the sales events data. In the sendBuyerInfoForm() function, the request URL is constructed by concatenating the values of various parameters.

3. The responsibility of startProcessSaleAddrs() is to screen out the sale events that fall outside the specified radius. The searchSale servlet has already made sure that all sale events in the current pool are located in the same state as the user's home address and are organized on the date specified by the user. The challenge here is to deal with driving distance.

4. There are several interesting technical points. First, the function uses var sales = eval(salesinfo) to convert the JSON string into a JavaScript array of objects. This is one nice feature of JSON.

5. Second, the function invokes the Google Maps geocoding service for checking driving distance. Because the data of any XHR call must be processed by a callback function, given a list of sale event addresses, there is no way to use a loop that calls the geocoding service (synchronously) and processes driving distance one by one. Instead, the loop must be indirectly implemented using recursion. Function getDistance() is used for this purpose.

6. To calculate the distance of each element to the client address, function getDistance() first retrieves the current address by using the counter curIdx. Then it relies on geoCoder to query the Google geocoding service for the geopoint of the address. This call is asynchronous. Once data arrives, the asynchronous callback function uses the function distanceFrom() provided by Google Maps to calculate its distance from the client address. Then it recursively calls getDistance() to process the next address until all addresses are processed. When recursion ends, showAllSaleAddrs() is called for displaying those sale events that are located within the specified radius.

7. Now the distance of each sale event to the user's home address is stored by getDistance() in an array called arrDistances. Function showAllSaleAddrs() can simply use a loop to compare each element in arrDistances with the maximum radius specified by the user. If the driving distance of an event is smaller, function showCompleteAddr() is used for displaying an address on the map.

8. Function showCompleteAddr() first invokes the geocoding service for the street address. Once data arrives, it adds one marker to the Map IDE. It is also responsible for setting up the click event of the marker so that the list of items can be displayed.

There are some other assisting JavaScript functions defined in Listing 8.10.3. For example, function initMap() initializes the Google Maps object in the page. It first checks whether the page is compatible with the Google Maps service and then creates one instance each of GMap2 and GClientGeocoder. The constructor of GMap2 needs an instance of the HTML DIV element for displaying the map. This is done using document.getElementById(“map_ide”) for locating a DIV element named map_ide. The initMap() function is called when the page is loaded.

Handling the Online Order and Shopping Cart. Once the marker of a sale event is clicked, the details of each item available at the event are displayed (including a thumbnail image, product description, price information, and a link for ordering the item). Function showCompleteAddr() must handle the delicate details of setting up these customized markers.

When showCompleteAddr() first creates a marker, detailed information on the items has not arrived yet. In this case, the function must first create a DIV element to hold the contents of the marker but leave the contents of DIV to be CONTENTS TO BE LOADED. The code also sets the attributes of the newly created DIV. For example, the id attribute of the DIV is the ID of the sale event (so that later when the information about the items arrives, the page can find out the DIV). The newly created DIV is then inserted as a child of a global DIV called divHidden, which is used to store information about the collection of sale events.

The second step of showCompleteAddr() is to send out request to servlet getSaleItems for retrieving the information of all items of the sale event. Once data is returned, the contents of the aforementioned DIV are populated. Then once the marker is clicked, the list of items can be displayed.

Java Servlet getSalesItem is used to help showCompleteAddr() in customizing markers. The source code of getSalesItem is displayed in Listing 8.10.4. The servlet, given the id of a sale event, returns a snippet of HTML code that displays the information of the items available at the yard sale event. As shown in Listing 8.10.4, the servlet first establishes a database connection and retrieves the information of each related sale item (e.g., price, description, and timestamp of lock.) Then an HTML table cell is constructed for each sale item, which consists of a thumbnail image and the price information. The servlet checks the last lock time of the item. If the item is still locked, string not available is displayed after the price of the item; otherwise, a hyperlink, Order, is created, which triggers a JavaScript function, lockItem.

The code of JavaScript function lockItem and the assisting function addItemToShopCart is displayed at the end of Listing 8.10.3. lockItem() sends a request to a servlet called lockItem and calls addItemToShopCart to add the item (its thumbnail image and price) to the shopping cart. addItemToShopCart() constructs the HTML snippet for the item and at the same time updates the value of the total amount of expenditure. They use the same technical approaches as showCompleteAddr() for XHR calls and processing of HTML contents.

Java Servlet lockItem is called by JavaScript function lockItem() for locking an item for 20 minutes. As shown in Listing 8.10.5, servlet lockItem tries to place a lock on a item given its identifier. If the item has been locked by others, the servlet returns failure; otherwise, the servlet returns a hybrid result that consists of three lines: (1) the success result with the identifier numbers of the item and the sale event; (2) the price of the item; and (3) a snippet of HTML code, which displays the details of the item, and link Drop, which drops the item from the shopping cart. The details of Drop action are not given. This task is left to you as a programming assignment.

Listing 8.10.4

Source Code of getSaleItems.java

images

images

images

Hands-On Practice

 

1. Create the MapOps.js file. In the project pane, right-click the Big-PeachYardSaleExpress node; select New and then Empty File. Enter MapOps.js as the file name, and click the Browse button. Select web/js as the container folder, and click OK. Then enter the code in Listing 8.10.3 into the file and save the file.

2. Create the searchSales servlet. Right-click the BigPeachYardSaleExpress node, and select New and then Servlet. Enter searchSale as the name of the servlet and click the Finish button. Enter the code of Listing 8.10.1 into the file. Replace the old processRequest() function generated by NetBeans with the processRequest() in Listing 8.10.1, and append the getSalesInJson() right after processRequest(). Right-click in the editor and select Fix Imports and then press F11 to compile the program.

3. Create the getSaleItems servlet. Repeat step 2 to create a new servlet named getSaleItems and then enter the code in Listing 8.10.4. Fix imports and compile the program.

4. Create the lockItem servlet. Repeat step 2 to create a new servlet named lockItem and then enter the code in Listing 8.10.5. Fix imports and compile the program. When resolving imports, for the Timestamp class, java.sql.Timestamp should be imported.

Source Code of lockItem.java

Source Code of lockItem.java

images

images

images

5. Update MapIDE.html. Remove the code between <title>SaleShop-ping Planner</title> and </head>, and enter the code in Listing 8.10.6. You need to replace the Google Maps key XXX_YOUR_KEY_YYY with your own Google Maps key. You can apply for a Google Maps key at http://code.google.com/apis/maps/signup.html. Use http://localhost:8080/ as the URL of your project when applying for the service key.

6. Modify the DIV element titled shopping cart. Replace Shopping Cart goes here with the following.

images

7. Add the DIV element for the Google Maps control and the hidden DIV for collecting data about sale events. Append the following right after the line MAP CONTENTS GO HERE.

images

Right-click in the editor and select Reformat Code.

Listing 8.10.6

HTML snippet of MapIDE.html

images

images

8. At this moment, the Acquire BuyerId button is not implemented in the sample project. The “11111” is used as a hard-coded transaction ID for the buyer. However, there is a foreign key dependency by the TBL_ITEM table on transaction ID. You cannot lock an item by using transaction ID “11111” if it is not in the database yet. To make sure that the program will run, you must first insert a record for transaction ID “11111” in the database.

Click the Services tab of the project pane, and extract the database node and then the tables node. Right-click on TBL_TRANSACTION, and then select View Data. Replace the SQL command in the command editor area with the following and execute it.

images

9. Verify the implementation. Press F6 to run the project. Click the Seller link and create one sales event, and then upload some items. The address of each event should be located within the radius of the home location when you later submit the query.

10. Press F6 to run the project. This time click the Buyer link. Specify the street address, date, and the radius of the query and then click the Search button. The sale events should show up in the map editor. Clicking any event on the map, you should see the list of items displayed, as shown in Figure 8.10.1. Click the Order link of each item, and you should see the item information displayed in the shopping cart (and the total amount is changed correspondingly). If you try to order the same item twice, a warning message should pop up.

8.11 Milestone 8: Itinerary Planner and Drag and Drop

 

The last section introduces you to the drag-and-drop feature provided by the Dojo framework. You will use the geocoding service by Google Maps for implementing a fancy itinerary planner. Users can drag and drop itinerary items, and your itinerary planner can automatically compile the list of arrival and departure times for each stop in the itinerary. All advanced features are implemented at the client side. You will learn to use cascading styles, event trigerring, and data conversion between JavaScript and JSON.

The development plan is as follows. First, you will modify the Map_IDE.html file to include the HTML elements needed for the new features. For example, the third accordion pane on the left side of the window will be populated for displaying itinerary items. Also, a DIV element must be embedded in the page for displaying driving directions. Second, a collection of JavaScript functions will be added for calculating arrival time and supporting drag and drop.

Using drag-and-drop features requires defining several cascading style rules. These style classes are defined in Listing 8.11.1 (listed within the <style> tag). The Target style defines the container class for the itinerary items. Each Target container has a 1px dotted gray border, and its width and height are 350px and 800px, respectively. Then several style classes for different behaviors of a drag-and-drop item are defined. The Mapdialog class defines the visual appearance of the DIV control that is used to display the textual description and map of driving directions.

images

Figure 8.11.1

The Itinerary Pane

Listing 8.11.1

Style Classes for Drag and Drop

images

Figure 8.11.1 shows the itinerary pane, which has three rows. The first row displays the home address of the client. The second row contains a button that once clicked, recomputes the itinerary. The third row is a target container, which contains the itinerary items that users can drag and drop. In Figure 8.11.1, there are two yard sale events in the itinerary. For each stop, BigPeachYardSaleExpress provides information about the identifier of the sale event, the estimated arrival and departure times, the address of the event, and a list of items. There is an additional textbox for the user to specify how long he or she plans to stay at the sale event. To achieve the look of Figure 8.11.1, you must embed the contents of Listing 8.11.2 in the itinerary pane. HTML table is used to set up the layout.

Listing 8.11.2

Contents of the Itinerary Pane

images

Once the LoadDirection button (in Figure 8.11.1) is clicked, a DIV will be popped up for presenting driving directions. Listing 8.11.3 displays the HTML source code for such a DIV element. The layout of the DIV is also achieved using HTML table. The table has two rows. The first row has two cells, one for textual description of driving direction and the other for presenting the map. The second row has a button that is used for toggling the visibility of the whole DIV control.

Listing 8.11.3

HTML Control for Displaying Driving Directions

images

To achieve drag and drop, you must define several JavaScript functions. These functions are listed in Listing 8.11.4. You will examine some of the assisting functions first.

Assisting JavaScript Functions: The first function in Listing 8.11.4, i.e., the initItinerary(), is used for initializing the drag-and-drop containers and the Google Maps object for computing driving directions. The function first creates an instance of dojo.dnd.Source by taking DIV container2 and sets up the callback to a function called itItemCreator() for initializing drag-and-drop items.

The itItemCreator() function (the fourth function in Listing 8.11.4) is essentially a constructor function. It is called whenever a drag-and-drop item is created. Given the input parameter named data, which contains the saleID and complete address of a sale event, the function will return a JavaScript object that contains three parts: (1) an HTML DOM node, (2) a data object, and (3) a list of drag-and-drop items. The Dojo framework will then take the returned object by itItemCreator() and create the visual appearance of the item for drag and drop. The first part of the return value, i.e., the HTML node, is an HTML DIV element. It has several attributes. For example, the id attribute of a node is the concatenation of a constant string ititem_ and the actual sale ID of the event. The innerHTML of the DIV control is a table that displays the contents of a yard sale in the itinerary: the sale ID, the arrival and departure times (which will be handled by driving direction computation), and a list of thumbnail images.

Listing 8.11.4

JavaScript Functions for Drag and Drop

images

images

images

images

Inserting New Itinerary Stops: When the Order link of an item (in Map IDE) is clicked, function addItemToItinerary() will be called to add an item into the corresponding sale event in the itinerary. It searches for the DIV element that contains the collection of items related to the event first and then adds the new item into the collection. If the item to be added is the first item for the event, function addSaleLocationToIntinerary() is called for adding the sale event as a new stop in the itinerary. addSaleLocationToIntinerary() simply calls the insertNode() function provided by Dojo to insert a new drag-and-drop item into the container.

The last task will be to display driving directions and compute the arrival and departure times for each sale event. Functions toggleDiv() and printTime() are two assisting functions. Function toggleDiv() toggles the visibility of a DIV element between the hidden and visible state. It is used to show and hide the DIV element that displays driving directions. Function printTime() prints out a date-time object in hh:mm:ss format.

Once the LoadDirection button is clicked, function LoadDirection() is used to load the list of street addresses of sale events into Google Maps and to display the corresponding driving directions. It first collects an array of complete addresses from the items in the itinerary pane. The home address of the user is the first element of this array. Then it calls the loadFromWaypoints() function provided by the GDirections (Google Maps Driving Directions) object, which loads the array of street address into the Google Maps object. Function updateArrDepatureTime() is then called by LoadDirection() to reset the departure and arrival times of each sale event, depending on the estimated driving time reported by Google Maps. Function updateArrDepartureTime() queries the GDirections object to get a list of GRoute objects. Each route corresponds to the driving route from one sale event in the itinerary to the next one. By invoking the getDuration() function provided by GRoute, updateArrDepartureTime() can calculate the departure and arrival times for each sale event. It then resets the corresponding HTML labels for each event to display the updated departure time.

Hands-On Practice

 

1. In MapIDE.html, locate the code snippet that loads the Dojo library. Append the following right after "dojo.require(“dijit. form.Button”);”.

images

2. Append the contents of Listing 8.11.1 (style classes for drag and drop) right after the following line in MapIDE.html.

images

3. Embed the HTML snippet in Listing 8.11.2 into the itinerary pane. To accomplish the goal, in MapIDE.html, find a DIV element that starts with <div DojoType=“dijit.layout.AccordionPane” title= “Itinerary”>. Embed the snippet of Listing 8.11.2 between the <div> and </div> tags (and remove the string Itinerary Info).

4. The next step is to insert one DIV element for storing driving directions. Simply insert the HTML snippet in Listing 8.11.3 right before the </body> tag in MapIDE.html.

5. In the MapIDE.html file, find one function named initMapIDE. In the function body (line 3), uncomment the //initItinerary(); statement.

6. Append the JavaScript functions (the contents of Listing 8.11.4) to MapOps.js.

7. Verify the implementation by adding some items into the shopping cart. Extract the itinerary pane. You will be able to see the corresponding sale events in the itinerary. Drag and drop the sale events to readjust their order. Enter the planned stay time for each event and click the Get Directions button. The driving directions will be displayed.

When entering the planned time for each event, you might need to right-click on the corresponding textbox and then select Select All to make sure that it receives the input focus.

8.12 Conclusion

This chapter has presented to you a large collection of server-side and client-side techniques for constructing a sophisticated Ajax web application. At the server side, you have had experiences with database programming, e.g., dynamic construction of a SQL query by using JDBC and the data table control provided by the Visual Web Pack of NetBeans. Java Servlets have proved to be a great tool for serving asynchronous requests, whereas JSP is convenient for displaying dynamic content. At the client side, you have had access to state-of-the-art JavaScript techniques. Using asynchronous XMLHttpRe-quest calls, you can dynamically update the contents of a web page. Many interesting functions are implemented using the asynchronous call, e.g., accessing the Google Maps service, calculating driving distance, retrieving thumbnail images of items, and searching for sale events that satisfy a user's query criteria. To enrich the user's experience, the Dojo framework is used to provide many fancy features, e.g., animation effects in dynamic advertisement banners and the support of drag and drop.

Ajax is not one single technique. It is a new way of delivering web applications to users. In an Ajax application, the user-server interaction is not the simple request-response mode anymore. Given the asynchronous nature of Ajax, developers must be more cautious about handling shared data among multiple asynchronous requests. This means more effort in debugging and testing at both the server and client sides.

8.13 Self-Review Questions

1. Which of the following are benefits of Ajax?

a. Ease of programming

b. Partial refresh of a huge web page

c. Richer user experiences

d. All of the above

2. At the server side, Ajax does not rely on a specific web application platform, e.g., ASPNet.

a. True

b. False

3. Which of the following data formats can be returned by an XHR call?

a. Plain text

b. XML

c. HTML

d. JSON

e. All of the above

4. Compared with the pure Java Servlets or Java-Server Pages (JSP) techniques, the JavaServer Faces (JSF) technique is more powerful and allows maximum flexibility in generating HTML contents.

a. True

b. False

5. With Flow Layout, the rendering of controls within a JSF web page is based on their absolute coordinates.

a. True

b. False

6. With a cache row set named rowSetOne, the statement rowSetOne.setString(2, “abc”); does which of the following?

a. Sets the value of the second column in the result to abc

b. Sets the value of the third olumn in the result to abc

c. Sets the value of the second parameter in the SQL query to abc

d. Sets the value of the third parameter in the SQL query to abc

7. By executing the JavaScript statement setTimeout(“callMe()”,2000), the callMe() function will be executed every 2 seconds.

a. True

b. False

8. The Dojo framework provides which of the following?

a. Sophisticated page layout using various Dojo panes such as split pane

b. Animation

c. Wr apper ofXHR call

d. dijit controls

e. All of the above

9. The startProcessSaleAddrs() function in Listing 8.10.3 can be stuck forever if any response from the geoservice of Google Maps service is lost.

a. True

b. False

10. To hide a DIV element named divOne, one can simply use a JavaScript statement, divOne.style.visibility = false, to disable its visibility.

a. True

b. False

Keys to the Self-Review Questions

1.d 2. a 3. e 4. b 5. b 6. c 7. b 8. e 9. a 10. b

8.14 Exercises

1. Discuss the pros and cons of the various server-side techniques presented in this chapter. (1) JavaServer Faces (JSF), (2) Java Servlet, and (3) JavaServer Pages (JSP).

2. Discuss the pros and cons of the various techniques for accessing background databases. (1) JDBC and (2) JSF data table and rowSet.

3. If a JavaScript snippet is returned by an XHR call, how can you execute the snippet on the fly?

4. Describe how you can execute a JavaScript function called repeatIt() every 2 seconds.

5. Describe how you can monitor and intercept all data communication of an Ajax web application.

8.15 Design Exercises

1. Improve the selfCheck() function in YardSale.java. You need to finish the format checking of ZIP codes at least.

2. Reset the layout of PostItem.jsp (using HTML table) so that it includes the dynamic advertisement banner.

3. Find a way to reset the height of layoutPanel in PostItem.jsp so that it grows with the data table.

4. Create two more dynamic advertisement samples by using the Dojo animation framework.

5. Implement the Acquire BuyerID button in the BuyerInfo pane of MapIDE.html and change the back-end code implementation so that the magic number “11111” is not used as the buyer transaction ID anymore.

6. Implement the Drop button in the shopping cart pane of MapIDE.html.

7. The startProcessSaleAddrs() function in Listing 8.10.3 can be stuck forever if one response from the geoservice from Google Maps is lost. Think of a way to enhance the reliability and robustness of the application.

8. Enhance the itinerary pane of the application by providing better support for handling exceptions. For example, provide exception handling code for function loadDirection() in Listing 8.11.4 in case the Google Maps service cannot resolve the geographical coordinates of a street address.

9. Update the home address textbox of the itinerary pane in MapIDE.html whenever the buyer information is updated.

10. Develop a complete test plan for BigPeachYardSaleExpress. Consider how you can evaluate the following quality attributes: (1) reliability, (2) robustness, and (3) security.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset