Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the...

32
1 Chapter 2 described the requirements for a good presentation-tier architecture and briefly compared the advantages and disadvantages of two candidate architectures. This bonus material will explore the two candidate presentation-tier architectures in depth, describing their individual solutions to the presentation-tier requirements. The first architecture, a JSP-centric architecture, uses JSP pages alone to meet the presentation- tier requirements in a fairly low-tech approach to the problem. The second architecture, a servlet-centric architecture, uses JSP pages and servlets in a more complex and flexible model-view-controller design and represents a more state-of-the-art presentation-tier architecture. Person Tracker Example Application We’ll explore the design details of both architectures and highlight their similarities and differences by building a simple Person Tracker Web application using each of them. The Person Tracker application maintains a list of people and allows users to view the list and edit individuals according to the navigational flow depicted in Figure 1. Comparing Candidate Web Application Architectures BONUS

Transcript of Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the...

Page 1: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

1

Chapter 2 described the requirements for a good presentation-tier architecture andbriefly compared the advantages and disadvantages of two candidate architectures.This bonus material will explore the two candidate presentation-tier architectures indepth, describing their individual solutions to the presentation-tier requirements. Thefirst architecture, a JSP-centric architecture, uses JSP pages alone to meet the presentation-tier requirements in a fairly low-tech approach to the problem. The second architecture,a servlet-centric architecture, uses JSP pages and servlets in a more complex and flexiblemodel-view-controller design and represents a more state-of-the-art presentation-tierarchitecture.

Person Tracker Example Application

We’ll explore the design details of both architectures and highlight their similarities anddifferences by building a simple Person Tracker Web application using each of them. ThePerson Tracker application maintains a list of people and allows users to view the listand edit individuals according to the navigational flow depicted in Figure 1.

Comparing Candidate WebApplication Architectures

B O N U S

28128X WS.4 7/28/03 12:48 PM Page 1

Page 2: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Figure 1 Person Tracker navigation flow.

The list and edit pages in the application are shown in Figures 2 and 3. The list pageprovides links to edit or delete an existing person and a link to create a new person,and the edit page is a standard HTML form used to edit a person’s information.

Figure 2 Person Tracker list page.

Save

Person List Page

Name1Name2Name3...

SuccessFailure

Person Edit Page

Salutation...Last Name

Process Form

2 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 2

Page 3: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Figure 3 Person Tracker edit page.

Although the example program is small and uses simple interface elements, bothJSP-centric and servlet-centric implementations will meet the presentation-tier require-ments and provide a foundation for discussing the candidate architectures.

Both implementations employ a simple stateless service Java object, PersonService,as the business-tier component responsible for managing model objects. PersonService, available for review at the companion Web site (http://www.wiley.com/compbooks/masteringweblogic), is a simple Java class that maintains a list of Personobjects in memory and provides a straightforward interface for retrieving, creating,and updating people.

These two components are all you need for business-tier components in the Person-Tracker application because we are concentrating on the presentation-tier architecture.Chapters 6 and 7 in the book discuss realistic business-tier architectures in more detailand make recommendations appropriate for actual applications.

Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach first.

JSP-Centric Architecture

The JSP-centric architecture we chose for this example uses only a single presentation-tier technology, JSP pages, to produce a Web application meeting the presentation-tierrequirements. The emphasis is on reducing complexity by eliminating all layers, tech-nologies, and components not absolutely necessary to the design.

Comparing Candidate Web Application Architectures 3

28128X WS.4 7/28/03 12:48 PM Page 3

Page 4: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Figure 4 JSP-centric architecture components.

Figure 4 presents a high-level picture of the JSP components and their interactions inthe architecture. Note that although everything in the presentation tier is implementedas JSP pages, there is still a controller component (called an action page in this archi-tecture). This approach is basically an all-JSP implementation of the model-view-controller architecture.

In addition to the three JSP pages and two business components illustrated in Figure 4,common utility functions and behaviors available to all JSP pages have been placed in abase class, MyJspBase. This class is defined as the base class for all JSP pages in the appli-cation using the <%@ page extends=”...” %> directive in each page. Apart from a stylesheet and error page, that’s it! We’ve obviously reduced the number of components andtechnologies to the bare minimum in this architecture.

Full source listings of the JSP components are not included in this material. Our goalis to walk through the presentation-tier requirements outlined in Chapter 2 and indicatehow a typical JSP-centric architecture meets them rather than provide a detailed exami-nation of this example program. Please download the example code from the companionWeb site if you wish to examine the components themselves in greater detail.

JSP Pages Perform Display TasksIn the JSP-centric architecture, JSP pages are responsible for all of the display-relatedrequirements outlined in the previous section. The ShowPeople.jsp page displays a listof model objects using simple scriptlet code to fetch the collection and loop through itto create the list display. The PersonService is used to fetch a collection of Personobjects at the top of the page:

<% Collection personList = PersonService.getPersonList(); %>

A page-scope bean called person is defined using the jsp:useBean directive, and thereference is iterated through the collection of people using scriptlet code:

<jsp:useBean id=”person”

class=”mastering.weblogic.ch02.example1.objects.Person”/>

Save

ShowPeople.jsp

Name1Name2Name3...

PersonService

SuccessFailure

EditPerson.jsp

Salutation...Last Name

EditPerson_action.jsp

Create,Update

FindByID

Person

4 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 4

Page 5: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

...

<%

Iterator i = personList.iterator();

while (i.hasNext()) {

person = (Person)(i.next());

%>

<tr>

...

</tr>

<% } // end while %>

</table>

</td>

</tr>

By declaring the person page bean, you can use jsp:getProperty elements in the tablecells to reduce scriptlet code:

<tr>

<td class=”table-data”><jsp:getProperty

name=”person” property=”salutation”/></td>

<td class=”table-data”><jsp:getProperty

name=”person” property=”firstName”/></td>

<td class=”table-data”><jsp:getProperty

name=”person” property=”middleName”/></td>

<td class=”table-data”><jsp:getProperty

name=”person” property=”lastName”/></td>

...

</tr>

The net result is a table of information on all people retrieved from the Person-Service and a display similar to Figure 2.

The [Edit] hyperlink for each person specifies the target page, EditPerson.jsp, alongwith the id of the person to edit and the type of action requested (update). We’ll discussthis mechanism in detail in a moment when we cover the navigation requirements.

The EditPerson.jsp page illustrates the chosen method for displaying model data inHTML forms. Request parameters are first extracted to determine the action and id val-ues for this display request. The display of a particular Person in the HTML form ele-ments is made possible by the jsp:useBean element, which defines the object and thejsp:getProperty elements used in the INPUT tags in the HTML form. The jsp:useBeanelement looks like this:

<jsp:useBean id=”person” scope=”request”

class=”mastering.weblogic.ch02.example1.objects.Person”>

<%

// code in here is executed only if person is absent from request

if (action.equals(“update”)) {

person = PersonService.findPersonById(id);

}

else {

person = new Person();

Comparing Candidate Web Application Architectures 5

28128X WS.4 7/28/03 12:48 PM Page 5

Page 6: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

}

submitToken = getSubmitToken(session); // get one if fresh display

%>

</jsp:useBean>

The jsp:getProperty elements used to extract data from the Person object look likethis:

<input type=”text” name=”firstName”

value=”<jsp:getProperty name=”person” property=”firstName”/>”

size=”50”/>

We’ve taken advantage of the behavior of body content in the jsp:useBean elementas a sort of conditional loading of the Person object from the service if it is not found inthe HttpServletRequest. Normally this page is displayed as a result of the hyperlink inthe list page, and no Person object will be found in the request. It is only during errorprocessing and form redisplay that it might be in the request, a condition that will beexplained later in this section. For now, assume the Person is not found in the request.The scriptlet code in the jsp:useBean element is therefore executed, and the page loadsthe person reference with the result of a findPersonById() call to the PersonService in the case of an update, or with a new, empty model object in the case of a create. Ineither case, the person reference is now valid for use in the jsp:getProperty elementsembedded in the HTML form.

Additional display-related presentation-tier requirements were identified earlier inthe chapter that we have not implemented in this JSP-centric example. Although stylesheets are used to control output format and colors, no allowance is made for role-based views of data or internationalization, or for reusing these components in otherapplications. Solutions for these requirements could be developed without introduc-ing significant additional complexity or presentation-tier components through the useof additional helper and utility functions in the JSP base class.

So far, it seems fair to say that this simple JSP-centric architecture has passed muster.There are no glaring deficiencies or limitations, at least not yet. Let’s move on to thenext series of requirements and see if the architecture continues to hold up.

Action JSP Pages Process Form SubmissionsThe choice of a JSP-centric approach dictates that HTML forms will be submitted to JSPpages for processing, but it does not actually specify which JSP page should performthe processing. There are at least three different options:

■■ Self-posting forms use the current JSP page as the target of the HTML form. Thevalidation and processing logic for the form is typically implemented at the topof the JSP page using scriptlet code or page beans. If the processing is success-ful, the scriptlet code forwards or redirects to the next page in the site. If theprocessing is unsuccessful, execution is allowed to fall through to the form-display HTML code again for error presentation and data redisplay.

6 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 6

Page 7: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

■■ Next-posting forms post their data to the next form in the process. The next JSPpage is responsible for validating and processing the form data for the previouspage and either redirecting back to the previous page in the case of errors orfalling through to the next HTML form display if successful.

■■ Action-page-posting forms post to intermediate action JSP pages, which are solelyresponsible for validating and processing the form data from the page. Theseaction pages are often named similarly to the JSP page for which they processdata (that is, EditPerson.jsp posts to EditPerson_action.jsp) and have no roleother than processing form data and forwarding or redirecting to the appropri-ate display page. In a sense, they are simple JSP versions of the controllerservlets often associated with model-view-controller designs.

The first two options suffer somewhat from the mixed-programming-mode prob-lem: The same JSP pages are being used to display data and process form data. This canlead to some unnecessary complexity and tight coupling between pages unless stepsare taken to abstract form processing and navigation. Solutions that employ either self-posting or next-posting forms almost invariably introduce page beans or abstract formsubmission handlers to reduce the complexity as much as possible.

We’re going to employ the third option, action JSP pages, a straightforward solutionusing separate JSP pages designed for validating and processing HTML form data. Theexample application has a single action JSP page, EditPerson_action.jsp, designed toprocess the form submissions from the EditPerson.jsp page described previously.

Please download and examine the source for EditPerson_action.jsp before proceed-ing. Keep in mind the specific form/update requirements listed in the previous sectionas we walk through this action page in some detail to understand how it achieves thedesired functionality. Note that we’ve left client-side validation out of our example in the interest of simplicity because client-side validation rarely affects the choice ofpresentation-tier architecture.

First, the HttpServletRequest data is extracted and placed in an intermediate object.Because the Person model object is actually a simple Java bean, it can double as theintermediate object in this design. If the model object were an entity bean, this wouldnot be possible, and we would be forced to introduce a separate Java class or use aHashMap or similar structure as an intermediate object. The request data is extractedto the intermediate Person object using the jsp:getProperty element with the specialproperty=”*” syntax:

<jsp:useBean id=”person” scope=”request”

class=”mastering.weblogic.ch02.example1.objects.Person”/>

<jsp:setProperty name=”person” property=”*”/>

Note that the person bean is defined with a scope=”request” attribute in the jsp:useBean element. This will become important later during error handling and redisplay.

Next, validation is performed to verify the correctness of a special submission tokenpassed in the form data. This token is used to prevent erroneous resubmission of formsand will be explained in the next section.

Next, validation of the actual form data is performed using the intermediate Personobject:

Comparing Candidate Web Application Architectures 7

28128X WS.4 7/28/03 12:48 PM Page 7

Page 8: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

// Perform validation against the Person object loaded with form data

if (person.getLastName().equals(“”)) {

errors.add(“Last name is a required field”);

}

A simple ArrayList bean called errors is defined earlier in the page using a jsp:useBean element. This collection is used to contain errors encountered during formvalidation. In this simple example, there is only a single validation rule (nonempty lastname) in addition to the submission token check.

Next, the action page performs the proper error handling if errors were detected inthe validation:

// Return to form page if errors are encountered,

// leaving Person on request

if (errors.size() > 0) {

%>

<jsp:forward page=”EditPerson.jsp” />

<%

The presentation-tier requirement is that error messages are presented to the userand that previously submitted form data is redisplayed for correction and resubmis-sion. In the chosen design, all that is required is a forwarding of the request back to theJSP display page, EditPerson.jsp, because the design of both the action page and thedisplay page reflected this requirement.

Recall that both the Person intermediate object and the errors collection were definedwith jsp:useBean elements that had a request scope. As long as you use forward ratherthan redirect to return to the EditPerson.jsp page, these beans will be available in that dis-play page. The <jsp:forward> directive therefore abandons the processing in the actionpage and invokes the EditPerson.jsp page with the request parameters intact.

Let’s look at EditPerson.jsp again briefly and follow this thread through to comple-tion. At the top of the page we defined the person and errors object references with arequest scope:

<%— Retrieve person object from request (if redisplay of form)

or from service —%>

<jsp:useBean id=”person” scope=”request”

class=”mastering.weblogic.ch02.example1.objects.Person”>

<%

// code in here is executed only if person is absent from request

...

%>

</jsp:useBean>

<jsp:useBean id=”errors” class=”java.util.ArrayList” scope=”request” />

Because the Person bean is present in the request, the code in the body content of thejsp:useBean tag will not be executed, and the person reference will point at the inter-mediate object from the request containing data extracted from the previous form

8 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 8

Page 9: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

submission. Subsequent jsp:getProperty elements will therefore display the previouslysubmitted data in the input elements of the form.

In the same way, the errors collection will exist in the request if the page is beingdisplayed because of an error, causing the error display code to create the properdisplay:

<tr><td><%= makeErrorDisplay(errors) %></td></tr>

In this code snippet, makeErrorDisplay() is a helper method defined in the JSP baseclass that creates a snippet of HTML text using the contents of the errors collection. Theend result is a display similar to Figure 2.4 in the book, with errors listed above theform elements, and the elements representing the previously submitted data ready forcorrection and resubmission.

The final requirement of the form-handling process is the proper interaction withthe business-tier components to complete the processing requested by the form sub-mission. EditPerson_action.jsp includes the Java code required to invoke the propermethods on the PersonService business component to create or update the Personmodel object:

else {

...

// Process the request using the PersonService

String action = request.getParameter(“action”);

int id = Integer.parseInt(request.getParameter(“id”));

if (action.equals(“update”)) {

LOG.debug(“Updating person bean in database”);

PersonService.updatePerson(person);

}

else if (action.equals(“create”)) {

LOG.debug(“Creating person bean in database”);

PersonService.createPerson(person);

}

...

}

Obviously, this interaction is made easier by the simplistic PersonService objectencapsulating all work required to save this model object. If the business tier used EJBcomponents or other techniques the interaction might require additional code orhelper functions.

With this simple JSP-centric architecture, we’ve managed to meet the presentation-tier requirements related to form validation and processing, including the proper han-dling of errors. So far, so good; but now we come to an area that suffers from oursimple JSP-centric approach: navigation.

Navigation Controlled by View and Action PagesThree primary navigation requirements were outlined in the previous discussion ofpresentation-tier requirements:

Comparing Candidate Web Application Architectures 9

28128X WS.4 7/28/03 12:48 PM Page 9

Page 10: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

■■ Basic navigation definition, establishing the hyperlinks and navigation controlsin the site

■■ Outcome-base navigation, defining the movement through the site as a resultof processing success or failure, states of objects, or other parameters

■■ Form-submission and user-navigation safeguards, preventing erroneous resub-mission of HTML forms and improper movement through the site

The JSP-centric architecture as implemented in the example application does not fol-low the best practices related to the first two requirements. The ShowPeople.jsp page,for example, hard-codes the name of the page used to edit the Person object in thehyperlink for each object in the table:

<td class=”table-data”>

<a href=”EditPerson.jsp?action=update&id=...”>[Edit]</a>

</td>

The EditPerson_action.jsp processing page also hard-codes the EditPerson.jsp page,for use during error redisplay, and the ShowPeople.jsp page, for use upon successfulcompletion of processing. Changing the name of either page would require a codechange in EditPerson_action.jsp due to this tight coupling. Removing these hard-coded links and page names might require an external properties or XML descriptorfile, a mechanism for loading the contents of the file, and a helper function available tothe JSP page for mapping a logical name to a physical page name. Not particularly dif-ficult, but not really compatible with the JSP-only, low-tech approach this architectureis intended to represent. We believe that the marginal maintainability and flexibilitybenefits of removing this coupling between pages do not justify the added complexityfor applications adopting the JSP-centric architecture.

The third navigation-related requirement, however, is not negotiable. The opportu-nity for unanticipated data modification and spurious behavior from the Web applica-tion is too great if steps are not taken to prohibit resubmission of previously-submittedforms and properly handle user bookmarking and navigation via back/forward but-tons in their browser.

Let’s break this into two areas — form submission controls and navigationcontrols — and address the implementation details related to each area separately.

JSP-Centric Form Submission Controls

The basic concept of form submission control is to avoid scenarios in which the usersubmits a form, reaches the following target page, and either immediately or subse-quently backs up to the form page and resubmits the form again. There may be caseswhere this behavior is desired and acceptable, but in many cases it would cause seri-ous problems. Consider, for example, a form that orders a product or reserves a nonre-fundable seat on an airline flight.

The JSP-centric implementation presented in this chapter uses a token approach forcontrolling form submission. As shown in Figure 5, the technique places a unique tokenin the HTML form as a hidden input field during the original form creation and saves the

10 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 10

Page 11: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

matching token in the HttpSession for this user. When the form is submitted, the hiddenfield containing the token is passed in with the normal form parameters, allowing theprocessing page to compare the passed-in value with the current value in the session anddisallow the submission if they do not match. The required code is shown here:

// Check for submit token before validating or processing this form

String submitToken = request.getParameter(“submitToken”);

if (checkSubmitToken(session, submitToken) == false) {

errors.add(“This form has expired and may not be resubmitted...”);

%>

<jsp:forward page=”EditPerson.jsp” />

<%

}

The MyJspBase base class defines checkSubmitToken() as follows:

protected boolean checkSubmitToken(HttpSession pSession, String pToken)

{

String savedToken = (String)pSession.getAttribute(“submitToken”);

if (pToken.equals(“”) || savedToken==null || savedToken.equals(“”))

return false;

return (pToken.equals(savedToken)); // return true if valid token

}

Once validation has succeeded and the processing of the request begins, the token iscleared from the HttpSession using the clearSubmitToken() helper method to preventresubmission of this form at any point in the future. If the user backs up to the formand tries to submit it again, the same token would be submitted to the processing pagebut would no longer appear in the HttpSession, and the submit would be disallowed.

Figure 5 JSP-centric submission control uses tokens.

Save

HttpSession

submittoken

EditPerson.jsp

Salutation...submittoken

EditPerson_action.jsp

Page generationcreates unique tokenand places it in form and HttpSession.

Form processing comparespassed in token to value inHttpSession. Denies submission if different.Clears token from session.

Comparing Candidate Web Application Architectures 11

28128X WS.4 7/28/03 12:48 PM Page 11

Page 12: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

The code in EditPerson.jsp used to place the submit token in the HTML form con-tains a few nuances required to handle redisplay of the form properly in the case ofnormal validation errors. The submit token is preserved through these validation andredisplay cycles by obtaining it from the HttpServletRequest if it exists there:

// preserve the original submit token if we are handling error display

String submitToken = request.getParameter(“submitToken”);

A new submit token is obtained and placed in the HttpSession only if the Personbean being displayed in the form is new or retrieved from the PersonService directly.This is accomplished by placing the token-creation code in the body content of thejsp:useBean element that defines the Person bean, thereby ensuring that a token isgenerated only in the right conditions:

<jsp:useBean id=”person” scope=”request” ... >

<%

// code in here is executed only if person is absent from request

if (action.equals(“update”)) {

person = PersonService.findPersonById(id);

}

else {

person = new Person();

}

submitToken = getSubmitToken(session); // only if fresh display

%>

</jsp:useBean>

The MyJspBase base class defines getSubmitToken() as follows:

protected String getSubmitToken(HttpSession pSession)

{

String token = pSession.getId().substring(0, 40) + “-” +

System.currentTimeMillis();

pSession.setAttribute(“submitToken”, token);

return token;

}

This technique is in the spirit of a JSP-only solution and meets the associated display,form processing, and navigation requirements, but obviously it could stand some refin-ing and improving. Custom tags may provide an improvement, as might additionalhelper classes and more sophisticated processing logic. Nevertheless, we will retain thislow-tech approach to provide a relatively transparent example of the logic required tomeet all of the requirements.

12 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 12

Page 13: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

JSP-Centric Navigation Controls

Many potential issues are related to unusual user interaction with the site that must beeither guarded against or handled properly. We’ll discuss two of them: bookmarks andbacking up through POST requests.

The key thing to realize with bookmarks is that the browser is unaware of any server-side forwarding that might have occurred during the processing of the original request.As far as the browser is concerned, the URL is whatever it first requested from the server.

For example, if an HTML form submits to an action page, and the action page per-forms the processing and forwards (not redirects) to a process-complete page of somesort, the browser will display the HTML response from the process-complete page buthave the URL of the action page. If the user bookmarks this page, thinking he or she isbookmarking the process-complete page, and uses the bookmark later, he or she willactually be reexecuting the action page. Depending on the action, this could have dan-gerous or confusing consequences.

For this reason, you should use a redirect in the processing page to tell the browserabout the final page location and allow it to match content with URL properly. TheEditPerson_action.jsp page uses this redirect technique after a successful processing ofthe request to send the user back to the person list page. The performance penalty ofthe additional round-trip request cycle from browser to server is a small price to payfor trustworthy bookmarks.

BEST PRACTIC E Use HTTP redirects rather than server-side forwards inaction JSP pages after successful form processing to avoid problems withbrowser bookmarks.

Backing up through POST requests is another insidious side effect of using forwardsin processing pages. Again, the browser is unaware of the server-side forwarding tak-ing place in the processing page handling a POST request. In this example, assume theuser moves off the process-complete page to a new page and then hits the Back buttonon the browser toolbar. Back to what? To the browser, the previous URL was a POSTrequest to the processing page, so off it goes performing the processing again. Depend-ing on the browser, the user may even see a warning dialog and wonder what is goingon. Clicking Retry will resubmit the form to the processing page again with unknownpotential consequences.

BEST PRACTIC E Use redirects to specify the new display page coming outof processing pages to avoid the bookmark problem and the backing-up-through-POST problem.

Benefits and Drawbacks of the JSP-Centric ApproachBefore we move on to discuss an alternative presentation-tier architecture, let’s sum-marize the components required to implement the PersonTracker example program inthe JSP-centric approach and discuss the benefits and drawbacks of this approach.Table 1 lists the specific components required and their roles in the architecture.

Comparing Candidate Web Application Architectures 13

28128X WS.4 7/28/03 12:48 PM Page 13

Page 14: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Table 1 JSP-Centric Components

COMPONENT/FILE DESCRIPTION

Person.java Model object used for communication withPersonService and as intermediate object during formprocessing and error handling

PersonService.java Simple stateless service in business tier encapsulatingpersistence services for Person model objects

ShowPeople.jsp JSP page that fetches and displays a list of Personobjects

EditPerson.jsp JSP page displaying an HTML form allowing the creationand update of Person objects

EditPerson_action.jsp Action JSP page used to validate and process forms fromEditPerson.jsp and interact with the PersonService toperform the desired function

MyJspBase.java Custom base class for all JSP pages providing utility andhelper functions

The relatively small number of components required to implement the example pro-gram speaks to the reduced complexity of the JSP-centric approach.

To summarize, the benefits of the JSP-centric approach are the following:

■■ Small number of components required to build a given application

■■ Small number of technologies used, reducing the learning curve for inexperi-enced resources

The drawbacks include these:

■■ The architecture tends to produce a tightly coupled application with hard-coded page names.

■■ Action JSP pages are primarily Java code, but they cannot be developed, com-piled, and debugged as easily as pure Java code.

■■ The reuse of processing and validation logic is hampered by its placement inform-specific action JSP pages.

We recommend the JSP-centric architecture for small to medium-sized Web applica-tions having a relatively static organization and a low potential for reuse of presentation-tier components, especially for development teams lacking the experience and skillsrequired to implement more complex architectures properly. In these types of applica-tions the coupling and reuse drawbacks of the JSP-centric approach are outweighed bythe benefits.

BEST PRACTIC E Consider a simple JSP-centric approach for small tomedium-sized projects if the benefits of simplicity and reduced learning curveoutweigh the reuse and flexibility drawbacks.

14 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 14

Page 15: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Servlet-Centric Architecture

In this section, we will build the same example application using a servlet-centricarchitecture to provide a platform for discussing details of the servlet-centric approachand to compare the two approaches given the same business- and presentation-tierrequirements.

The servlet-centric architecture chosen for this example leverages an open-sourceservlet-centric framework called Struts to avoid building the required support compo-nents and logic from scratch. We’re going to use a small subset of the components andfeatures in the Struts framework, concentrating primarily on the features related toform handling and navigation. We will walk through all of the presentation-tierrequirements presented in Chapter 2 and identify the techniques and componentsused to satisfy these requirements in our example application.

Figure 6 presents a high-level view of the JSP, servlet, form, and model componentsand their interactions in the servlet-centric architecture chosen for this application.

There are still two main JSP pages, ShowPeople.jsp and EditPerson.jsp, but the com-ponents responsible for processing forms and controlling navigation have changedconsiderably in the new architecture. A new PersonForm object has been introducedfor use by the EditPerson.jsp page and related processing, and the diagram does notinclude configuration and properties files required by the architecture. There are morecomponents required in the servlet-centric approach, overall, than in the JSP-centricarchitecture depicted in Figure 4.

Figure 6 Servlet-centric architecture components.

Save

ShowPeople.jsp

Name1Name2Name3...

PersonService

SuccessFailure

EditPerson.jsp

Salutation...Last Name

EditPersonAction

ShowPeopleAction

Create,Update

Validate

FindByID

PersonForm

PersonForm

Person

Comparing Candidate Web Application Architectures 15

28128X WS.4 7/28/03 12:48 PM Page 15

Page 16: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Let’s walk through the presentation-tier requirements in the same manner as beforeand examine how the servlet-centric architecture meets them in our example applica-tion. You can download the example code from the companion Web site to have itavailable during the discussion that follows.

JSP Pages Perform Display TasksAs was the case in the JSP-centric approach, the servlet-centric architecture uses JSPpages to satisfy the display-related presentation-tier requirements. The new ShowPeople.jsp page, used to view a list of Person objects, is very similar to the JSP-centric version presented in the previous section. We’ll walk through portions of the page that are different from the earlier version to understand the use of various Struts tags andfeatures.

First, the Struts HTML tag library is declared with a JSP taglib directive:

<%@ taglib uri=”/WEB-INF/struts-html.tld” prefix=”html” %>

Two other tag libraries are available in the current version of Struts, providing logictags and bean-related tags that might also be useful in your application but are notrequired in this example. The Struts HTML tag library provides the custom tags neededto create HTML forms that meet the presentation-tier requirements with very little customcoding, as you will see in the discussion of the new EditPerson.jsp that follows.

The PersonService is used to fetch a collection of Person objects for display, as before,and the same jsp:useBean element defining the Person page bean and iteration logic areused to display HTML information for each Person object retrieved from the service.The individual attributes of the Person bean are again displayed using jsp:getPropertyelements in the loop.

The only significant difference in the new version of ShowPeople.jsp is the hyper-link placed on the right side of each row in the table and the hyperlink used for theCreate Person function at the bottom of the page. In the JSP-centric approach, theselinks were hard-coded references to the EditPerson.jsp page:

<a href=”EditPerson.jsp?action=create”>Create Person</a>

In the new page, the equivalent link invokes a controller component called Show-PeopleAction and passes along information required for the component to forward therequest properly:

<a href=”ShowPeopleAction.do?action=create”>Create Person</a>

The [Edit] hyperlink for each person likewise invokes the controller componentrather than linking directly to the EditPerson.jsp page. We’ll discuss the new navigation-control scheme and how these links are defined in the configuration file in more detailwhen we cover navigation requirements later in this section.

The EditPerson.jsp page illustrates more of the Struts-specific techniques for dis-playing model data in HTML forms. Please review this component in the download-able example code before proceeding.

16 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 16

Page 17: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

The first thing to recognize about the new EditPerson.jsp is the significant reductionin scriplet code and jsp:useBean elements compared with the JSP-centric version of thesame page. Much of this scriptlet code in the JSP-centric version was required toachieve the form-handling and navigation-control requirements in the absence of aframework that handles these requirements. The chosen servlet-centric architectureleverages the built-in form-handling and navigation-control features of Struts toeliminate almost all custom code in simple forms such as EditPerson.jsp.

The first important section of the page is the definition of the HTML form using theStruts html:form custom tag:

<html:form action=”/EditPersonAction”>

In the form itself, the HTML input and hidden elements are defined using additionalStruts custom tags:

<html:hidden property=”action”/>

<html:hidden property=”id”/>

...

<td><html:text property=”firstName” size=”50”/> ... </td>

Notice that we have not named the form or explicitly provided any page bean ormodel object for use in displaying the form. How does Struts know which Person todisplay?

The ShowPeopleAction controller component is responsible for loading the desiredmodel data into a special intermediate object called a form bean in the Struts frame-work, which in our case is a class called PersonForm. Special Struts configuration filesdefine the relationship between the ShowPeopleAction component, the PersonFormobject, and the EditPerson.jsp page, and the Struts framework takes care of the rest. Ittakes some work to get it all set up properly, but once you do, the JSP pages becomealmost trivial.

We’ll explain the configuration file and controller process in detail in the next twosections. For now, assume that the page has a PersonForm object available containingthe desired data and implementing get methods for each property required by theform. The html:text tags simply declare the particular property on the PersonForm tobe displayed in each HTML form element, and the tags create the equivalent input element.

A detailed discussion of the many Struts HTML custom tags is well beyond theintended scope of this material. Visit the Struts home page at http://jakarta.apache.org/struts for detailed documentation.

As in the JSP-centric approach, this simple example program has not truly imple-mented all of the display-related presentation-tier requirements outlined previously.Although style sheets are again used to control output format and colors, no allowanceis made for role-based views of data or internationalization. The Struts frameworkdoes include facilities for bundling messages and internationalizing the display pagesand messages; see the Struts Web site for details. We address role-based views of dataand efficient reuse of presentation-tier components during the construction of thelarger example program in Chapters 3 and 4 in the book.

Comparing Candidate Web Application Architectures 17

28128X WS.4 7/28/03 12:48 PM Page 17

Page 18: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

It seems safe to say that the servlet-centric architecture leveraging the Struts frame-work has met all of the display-related requirements and remains a viable candidate atthis point. Let’s move on and discuss an area in which we expect the servlet-centricarchitecture to shine: processing HTML form submissions.

Controller Components Process Form SubmissionsThe servlet-centric architecture employs servlets and other controller components tovalidate and process form submissions and handle related errors. Form pages such asEditPerson.jsp therefore post their form data into a controller component for processing.Different types of components can be used for this purpose:

■■ Dedicated controller servlets are individual servlet components designed tohandle the form processing for a single form JSP page. For example, you mighthave a servlet called EditPersonProcessorServlet used as the target for the Edit-Person.jsp page. This dedicated servlet can extract the form data, validate thecontents, and perform the necessary processing steps. This option is perfectlyacceptable for small applications requiring less flexibility than that affordedby the other options.

■■ Single controller servlet is a single servlet component designed to handle formprocessing for many different form pages. The controller servlet branches intodifferent validation and processing code based on hidden form fields or query-string parameters. All processing code is located in the common servlet itself inthis design, and a big switch or if-then-else construct is required to branch prop-erly for each incoming form page. As the number of forms grows, this servletgrows quickly in size and complexity and may even become a bottleneck in thedevelopment effort due to source-control contention between developers.

■■ Single controller servlet with action classes is also a single servlet component used byall forms, but the internal branching is accomplished by instantiating a particularaction or helper class and invoking methods on that helper class to perform thework. The processing logic for each page is located in the corresponding actionclass in this design. This option is ideal for medium- to large-scale Web applica-tions. Form validation and processing are accomplished by a single controllerservlet using helper classes that are specific to each input form. In the exampleprogram we employ a common Struts controller servlet called ActionServlet thatinstantiates and uses a helper class called EditPersonAction when processing apost request from EditPerson.jsp. This design is the standard Struts approach, butit could also be implemented in a custom servlet-centric architecture.

Figure 7 illustrates the interactions between the components involved in formprocessing in our servlet-centric design.

18 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 18

Page 19: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Figure 7 Servlet-centric form processing details.

The chosen servlet-centric architecture uses a fair number of components to meetthe form-processing requirements. We’ll walk through these requirements and explainthe related components in a moment, but first we need to introduce the most importantconfiguration file in the Struts framework: the struts-config.xml file. This file, shown inListing 1, defines all of the controller components and related classes and specifies therules regarding form processing and page navigation in the application. We’ll discussindividual sections of this file as we walk through the rest of the components.

<?xml version=”1.0” encoding=”ISO-8859-1” ?>

<!DOCTYPE struts-config PUBLIC

“-//Apache Software Foundation//DTD Struts Configuration 1.1//EN”

“http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd”>

<struts-config>

<form-beans>

<form-bean name=”personForm”

type=”mastering.weblogic.ch02.example2.PersonForm”/>

</form-beans>

<action-mappings>

<action path=”/ShowPeopleAction”

Listing 1 Struts-config.xml configuration file. (continued)

Save

ShowPeople.jsp

Name1Name2Name3...

PersonService

Success

Failure

EditPerson.jsp

Salutation...Last Name

ActionServlet

EditPersonAction

Create,Update

Extract Form DataCall Validate

PersonForm

Person

Call ExecutePass PersonForm

Comparing Candidate Web Application Architectures 19

28128X WS.4 7/28/03 12:48 PM Page 19

Page 20: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

type=”mastering.weblogic.ch02.example2.ShowPeopleAction”

name=”personForm”

scope=”request”

validate=”false”

input=”/ShowPeople.jsp”>

<forward name=”success” path=”/EditPerson.jsp” redirect=”false”/>

<forward name=”failure” path=”/ShowPeople.jsp” redirect=”true”/>

</action>

<action path=”/EditPersonAction”

type=”mastering.weblogic.ch02.example2.EditPersonAction”

name=”personForm”

scope=”request”

validate=”true”

input=”/EditPerson.jsp”>

<forward name=”success” path=”/ShowPeople.jsp” redirect=”true”/>

<forward name=”failure” path=”/Failure.jsp” redirect=”false”/>

</action>

</action-mappings>

</struts-config>

Listing 1 (continued)

Extracting Form Data

The Struts framework provides automatic extraction of HTML form data into a spe-cialized Java component called a form bean, normally derived from the Struts classActionForm. This form object is typically the same object used by the custom html tagsto display the form. There is a single form object in our example program, PersonForm,containing the attributes, get and set methods, and other validation and initilizationmethods required to override the ActionForm base class and contain the form data.Please examine the PersonForm class in the downloadable example code before proceeding.

The HttpServletRequest parameters created by the HTML form in EditPerson.jspare automatically copied to the corresponding attributes in the PersonForm object atthe beginning of form processing, much like a wildcard jsp:setProperty element in anaction JSP page. The PersonForm bean was declared in the struts-config.xml file withthe following elements:

<form-beans>

<form-bean name=”personForm”

type=”mastering.weblogic.ch02.example2.PersonForm”/>

</form-beans>

20 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 20

Page 21: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Server-Side Validation

After placing the form data in the bean, Struts invokes the validate() method on thePersonForm bean to allow basic data validation. This is a good location for low-levelvalidation checks that can be performed by the form bean alone without additionalcomponents or services. In this example, we’ve implemented the validate() methodand used it to check for the required lastName field:

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request)

{

System.out.println(“>> PersonForm::validate()”);

ActionErrors errors = new ActionErrors();

if ((lastName == null) || (lastName.length() < 1))

errors.add(ActionErrors.GLOBAL_ERROR,

new ActionError(“error.lastName.required”));

return errors;

}

The validate() method should return null or an empty collection of errors if no vali-dation problems are encountered. If a validation error does occur, an instance of theActionError class should be created and added to the list. Errors may be assigned to aparticular field such as lastName, or left global as shown in this example. The messagedisplayed to the user is retrieved from the ApplicationResources.properties resourcefile using the supplied key.

After the Struts framework invokes the validate() method on the PersonForm object,it proceeds to call the execute() method on the particular action class configured forthis action to complete the server-side validation and perform the desired processing.Recall the section in struts-config.xml related to this form:

<action path=”/EditPersonAction”

type=”mastering.weblogic.ch02.example2.EditPersonAction”

name=”personForm”

scope=”request”

validate=”true”

input=”/EditPerson.jsp”>

<forward name=”success” path=”/ShowPeople.jsp” redirect=”true”/>

<forward name=”failure” path=”/Failure.jsp”/>

</action>

You can see that the type attribute defines the EditPersonAction class, shown in List-ing 2, as the proper action class for this form.

package mastering.weblogic.ch02.example2;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.util.Locale;

Listing 2 EditPersonAction.java. (continued)

Comparing Candidate Web Application Architectures 21

28128X WS.4 7/28/03 12:48 PM Page 21

Page 22: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

import java.util.Vector;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionForm;

import org.apache.struts.util.MessageResources;

import org.apache.struts.util.PropertyUtils;

import mastering.weblogic.ch02.example2.objects.Person;

import mastering.weblogic.ch02.example2.services.PersonService;

public final class EditPersonAction extends Action

{

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws IOException, ServletException

{

System.out.println(“>> EditPersonAction::execute()”);

Locale locale = getLocale(request);

MessageResources messages = getResources();

HttpSession session = request.getSession();

ActionErrors errors = new ActionErrors();

PersonForm pform = (PersonForm) form;

// check for the transaction token set in ShowPeopleAction

if (!isTokenValid(request))

errors.add(ActionErrors.GLOBAL_ERROR,

new ActionError(“error.transaction.token”));

// Report any errors we discovered back to the original form

if (!errors.empty()) {

saveErrors(request, errors);

return (new ActionForward(mapping.getInput()));

}

if (pform.getAction().equals(“update”)) {

Person p = pform.getPerson();

if (servlet.getDebug() >= 1)

servlet.log(“ Updating person bean in database”);

PersonService.updatePerson(p);

}

Listing 2 (continued)

22 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 22

Page 23: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

else if (pform.getAction().equals(“create”)) {

Person p = pform.getPerson();

if (servlet.getDebug() >= 1)

servlet.log(“ Creating person bean in database”);

PersonService.createPerson(p);

}

resetToken(request);

// Forward control to the next page

if (servlet.getDebug() >= 1)

servlet.log(“ Forwarding to ‘success’ page”);

return (mapping.findForward(“success”));

}

}

Listing 2 (continued)

EditActionPerson derives from the Action base class provided by Struts and definesthe execute() method responsible for final server-side validation steps, the processingof the form, and any interactions with business-tier components. As shown in List-ing 2, the execute() method checks the submission token for validity and forwards pro-cessing back to the input page if any errors were detected by this check or the earlierPersonForm validation:

// check for the transaction token set in ShowPeopleAction

if (!isTokenValid(request))

errors.add(ActionErrors.GLOBAL_ERROR,

new ActionError(“error.transaction.token”));

// Report any errors we discovered back to the original form

if (!errors.empty()) {

saveErrors(request, errors);

return (new ActionForward(mapping.getInput()));

}

We’ll discuss the submission token and the use of the ActionForward mapping tech-nique in the next section when we discuss navigation.

Error Display

Like the JSP-centric solution, the servlet-centric solution must display validation errorsat the top of the form along with the original user input for correction. The execute()method forwarded processing back to the input page, EditPerson.jsp, in the case of val-idation errors, and the simple <html:errors/> tag in the JSP page is sufficient for dis-playing the errors placed in the ActionErrors collection during validation:

<tr><td><html:errors/></td></tr>

Comparing Candidate Web Application Architectures 23

28128X WS.4 7/28/03 12:48 PM Page 23

Page 24: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Because the Struts html custom tags are being used to create the HTML form elements,the original user input will be placed in these fields automatically for correction andresubmission by the user. Compare this automatic handling of error presentation andredisplay of input data with the complicated steps required in the JSP-centric approach tobetter understand the value the Struts framework brings to your development process.

Interaction with the Business Tier

After all validation rules are enforced and passed, the EditPersonAction componentmakes the appropriate calls on the PersonService to process the request:

if (pform.getAction().equals(“update”)) {

Person p = pform.getPerson();

if (servlet.getDebug() >= 1)

servlet.log(“ Updating person bean in database”);

PersonService.updatePerson(p);

}

else if (pform.getAction().equals(“create”)) {

Person p = pform.getPerson();

if (servlet.getDebug() >= 1)

servlet.log(“ Creating person bean in database”);

PersonService.createPerson(p);

}

Note that because the form parameters were extracted to a PersonForm object andthe interfaces in the PersonService require Person objects, we need to create a Personobject from the form data. The getPerson() helper method on the PersonForm class per-forms this task for us as a convenience.

That’s all there is to it. The Struts framework, PersonForm bean, and EditPerson-Action class are all that is required to meet the form-processing requirements. Thingsare looking good for the servlet-centric approach. Now let’s see if it can handle the nav-igation requirements.

Navigation Controlled by Configuration FilesRecall the three navigation requirements we identified in Chapter 2: basic navigationbetween pages, outcome-based navigation, and form submission and navigation safe-guards. The JSP-centric approach used hard-coded page names in display and actionpages in the interest of keeping things simple, a technique that did not meet all of thebest practices outlined for these navigation requirements. The use of Struts in theservlet-centric implementation, however, allows us to follow the best practices andmeet the navigation requirements through the use of configuration files.

As described in the previous section, the struts-config.xml file is the primary config-uration file for a Struts implementation. It defines each action in the system and pro-vides configuration information used during validation, form processing, andnavigation. We’ll first examine how this file is used to control both basic navigationand outcome-based navigation, and then we will examine the Struts mechanism forcontrolling form submission.

24 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 24

Page 25: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Servlet-Centric Navigation

The servlet-centric implementation we’ve adopted uses a form of the Dispatcher designpattern built into the Struts framework. In this design, JSP display pages includehyperlinks that invoke controller components rather than other JSP pages directly. Thecontroller components are then responsible for forwarding the request, along with anynecessary model data, to the appropriate next display page. In Struts, the controllercomponent is a combination of the standard ActionServlet and a custom-built Actionclass that encapsulates the desired logic.

Figure 8 illustrates the relationship between the ShowPeople.jsp display page, theShowPeopleAction custom action class, and the target JSP display page, EditPerson.jsp.

The ShowPeople.jsp page included links with a special target syntax:

<a href=”ShowPeopleAction.do?action=update&id=...”>[Edit]</a>

The hyperlink uses a target name with a specially mapped .do suffix and a nameequal to the desired action as it appears in the struts-config.xml file:

<action-mappings>

<action path=”/ShowPeopleAction”

type=”mastering.weblogic.ch02.example2.ShowPeopleAction”

name=”personForm”

scope=”request”

validate=”false”

input=”/ShowPeople.jsp”>

<forward name=”success” path=”/EditPerson.jsp” redirect=”false”/>

<forward name=”failure” path=”/ShowPeople.jsp” redirect=”true”/>

</action>

...

</action-mappings>

Figure 8 Servlet-centric navigation uses action class.

ShowPeople.jsp

Name1Name2Name3...

PersonService

EditPerson.jsp

Salutation...Last Name

ShowPeopleActionFindByID

PersonForm

Comparing Candidate Web Application Architectures 25

28128X WS.4 7/28/03 12:48 PM Page 25

Page 26: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

The configuration file specifies the Action class associated with the ShowPeople-Action action, a form bean available in the action, and additional information usedduring processing. Although a detailed examination of the many attributes andoptions available in the action element is beyond the scope of this discussion, we willexamine the forward elements to better understand how Struts controls navigation.

One detail required for proper Struts operation is the special mapping of the .do suffix to the Struts-provided ActionServlet in the Web application’s web.xml file:

...

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

...

<load-on-startup>2</load-on-startup>

</servlet>

<!— Standard Action Servlet Mapping —>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

...

There are many additional web.xml configuration elements required for the properoperation of Struts. We discuss these requirements in Chapter 4 in the book in the con-text of the larger example application.

As shown in Figure 8, the ShowPeopleAction class in Listing 3 is responsible forpreparing a PersonForm bean and forwarding control to the correct display JSPdepending on the outcome.

package mastering.weblogic.ch02.example2;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionForm;

import org.apache.struts.util.MessageResources;

import org.apache.struts.util.PropertyUtils;

import mastering.weblogic.ch02.example2.objects.Person;

import mastering.weblogic.ch02.example2.services.PersonService;

public final class ShowPeopleAction extends Action

{

public ActionForward execute(ActionMapping mapping,

Listing 3 ShowPeopleAction.java.

26 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 26

Page 27: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws IOException, ServletException

{

System.out.println(“>> ShowPeopleAction::execute()”);

// Populate the form before forwarding to edit page

PersonForm pform = (PersonForm)form;

// retrieve business object and set form bean attributes

if (pform.getAction().equals(“update”)) {

Person p = PersonService.findPersonById(pform.getId());

if (p == null)

return (mapping.findForward(“failure”));

pform.setValues(p); // use PersonForm helper function

}

// Set a transactional control token to prevent double posting

if (servlet.getDebug() >= 1)

servlet.log(“ Setting transactional control token”);

saveToken(request);

if (servlet.getDebug() >= 1)

servlet.log(“ Forwarding to ‘success’ page”);

return (mapping.findForward(“success”));

}

}

Listing 3 (continued)

Like the EditPersonAction class, the ShowPeopleAction class defines the execute()method to specify the desired behavior. We’ll walk through this method step by step.

First, the action attribute in the passed-in PersonForm bean is checked to see if thedesired action is update. If the hyperlink specifies a value for action in the query string,Struts populates this attribute in the form bean before invoking the execute() method.If we are updating rather than creating, the code fetches the desired Person modelobject from the PersonService and uses a helper method on the PersonForm bean topopulate its attributes from the fetched Person object.

You can also see the first example of outcome-based navigation demonstrated here:

if (p == null)

return (mapping.findForward(“failure”));

If the call to PersonService.findPersonById() returns null, the execute() method willredirect the user to a failure page based on a matching forward mapping element in thestruts-config.xml file for this action, in this case simply back to ShowPeople.jsp:

<forward name=”failure” path=”/ShowPeople.jsp” redirect=”true”/>

Comparing Candidate Web Application Architectures 27

28128X WS.4 7/28/03 12:48 PM Page 27

Page 28: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Next, a submission token is set in the request for use in controlling form resubmis-sion. We’ll talk about these tokens and how they work in the next section.

Finally, assuming everything went well, the execute() method ends by transferringthe user to the display page associated with the success mapping in the action config-uration, in this case the EditPerson.jsp page:

<forward name=”success” path=”/EditPerson.jsp” redirect=”false”/>

Note that we used redirect=”true” for the failure case and redirect=”false” for thesuccess case. Struts allows navigation using either form, but be careful that redirectionis not used when form beans or errors are placed in the HttpServletRequest for trans-fer because they will not be available after a redirect. We’ll talk more about pureforwarding versus redirecting later when we discuss navigation controls.

Servlet-Centric Form Submission Controls

Recall that form submission control attempts to avoid scenarios in which the user sub-mits a form, reaches the following target page, and subsequently backs up to the formpage and resubmits the form. The JSP-centric approach used a custom-developed setof helper methods in the MyJspBase base class and the placement of a special token inthe HTML form to avoid resubmission. The JSP-centric approach was fairly compli-cated, requiring a number of small pieces of code scattered across the form page, acrossthe action JSP page, and in the base JSP class.

Struts provides a facility for controlling form submission that works much the sameway as the custom-developed token mechanism used in the JSP-centric solution butrequires very little code to implement. You’ve already seen half of the required codewhen we examined the ShowPeopleAction class:

// Set a transactional control token to prevent double posting

if (servlet.getDebug() >= 1)

servlet.log(“ Setting transactional control token”);

saveToken(request);

...

The call to saveToken() is all that is required to include a special submit token in theHttpServletRequest passed along to the EditPerson.jsp display JSP page. In the displaypage, no additional code is required to include this token as a hidden field in theHTML form when the Struts custom tags are used to define the form:

<html:form action=”/EditPersonAction”>

...

</html:form>

If you examine the HTML output of this form in your browser you will see the hid-den token:

<input type=”hidden” name=”org.apache.struts.taglib.html.TOKEN”

value=”c3f79e58afda5238b5e528a6f5b27ea5”>

28 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 28

Page 29: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

The other half of the code required to control form submission appears in the Edit-PersonAction class:

// check for the transaction token set in ShowPeopleAction

if (!isTokenValid(request))

errors.add(ActionErrors.GLOBAL_ERROR,

new ActionError(“error.transaction.token”));

This simple call to isTokenValid() verifies that the passed-in token matches the lasttoken set for this user and allows us to trap erroneous submissions and add an error tothe ActionErrors collection we’re building during form validation. This error is treatedlike any other validation error, producing a redisplay of the form page again with theerror message displayed at the top of the form, as shown in Figure 9.

Finally, the EditPersonAction class clears the token after successful processing of therequest to effectively invalidate the token and preclude resubmission of that particularform:

resetToken(request);

The Struts technique outlined in this section is clearly superior to the custom-builtsubmission control technique used in the JSP-centric approach, although the underly-ing mechanisms are very similar.

BEST PRACTIC E Use the Struts-provided tokens to control form submission,rather than custom-developed techniques, to reduce complexity.

Figure 9 Improper form submission causes validation error.

Comparing Candidate Web Application Architectures 29

28128X WS.4 7/28/03 12:48 PM Page 29

Page 30: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

Servlet-Centric Navigation Controls

As we discussed in the JSP-centric implementation, there are many potential issuesrelated to unusual user interaction with the site that must be guarded against or han-dled properly. Again, we will concentrate on two of these issues: bookmarks and back-ing up through POST requests.

Rather than repeating the discussion from the JSP-centric section, we’ll simply statethat all of the same best practices apply to a servlet-centric approach. For example, it isstill a good idea to use a redirect in processing pages to tell the browser about the finalpage location for proper bookmarking and avoiding bad POST requests.

Fortunately, the Struts architecture makes it very easy to specify which type of trans-fer should take place at the end of a processing cycle or as the result of a simple dis-patcher request. The forward elements in the action mapping include a redirectattribute for this purpose. For example, in the EditPersonAction section of struts-config.xml the forward-mapping elements specify two different types of transfer:

<action path=”/EditPersonAction”

type=”mastering.weblogic.ch02.example2.EditPersonAction”

name=”personForm”

scope=”request”

validate=”true”

input=”/EditPerson.jsp”>

<forward name=”success” path=”/ShowPeople.jsp” redirect=”true”/>

<forward name=”failure” path=”/Failure.jsp” redirect=”false”/>

</action>

The success case will redirect to the ShowPeople.jsp page after a successful process-ing of the form, exactly the behavior we’re looking for. The browser URL will reflectthis page rather than the target of the HTML form, EditPersonAction.do, and all of thebookmark and user-navigation problems described previously will be prevented.Again, the performance cost associated with a redirect is a small price to pay for avoid-ing these navigation problems.

Why not always use forward mappings with the redirect attribute set to true?Remember that an HTTP redirect, in addition to requiring a round trip to the browser,also effectively discards any data placed in the current HttpServletRequest. Simplyput, an HTTP redirect causes a different HTTP request. If the controller componentneeds to make data, such as a form bean, available to the target page after a redirect, itmust place the data in the HttpSession rather than the HttpServletRequest by declar-ing the scope to be session in the action configuration.

Placing data in the HttpSession that is intended for a single use by the target JSPpage is not recommended. The HttpSession is intended for long-lived state informa-tion related to this user, not as a temporary holding place for transferring data betweenpage requests. One concrete reason to avoid using the HttpSession for these types ofresults is the additional overhead caused by session persistence. For example, if youare using in-memory replication in a clustered WebLogic Server environment, data inthe HttpSession must be replicated to the backup server for this user in case of failure.Placing large temporary objects on the session will therefore affect the performance ofthe entire cluster.

30 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 30

Page 31: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

We recommend HTTP redirects when no data must be passed to the target page andserver-side forwards when a form bean or other data is required by the target page. Inthe example program, we used a redirect after the successful processing of a form sub-mission to return to the ShowPeople.jsp page because no data was required for this target page. We used a server-side forward in ShowPeopleAction, however, becausethe controller had to fetch and populate the PersonForm object required by the EditPerson.jsp page, and we did not want to place this object on the HttpSession.

BEST PRACTIC E Favor HTTP redirects in Struts forward mappings to avoidbookmark and user-navigation problems, but use server-side forwards whennecessary to avoid placing model objects or form beans in the HttpSession.

Benefits and Drawbacks of the Servlet-Centric ApproachLet’s summarize the components required to implement our simple example programin the Struts-based servlet-centric approach and discuss the benefits and drawbacks ofthis approach. Table 2 lists the specific components required in the example applicationand their role in the servlet-centric architecture.

Table 2 Servlet-Centric Components

COMPONENT/FILE DESCRIPTION

Person.java Model object used for communication withPersonService

PersonService.java Simple stateless service in business tier encapsulatingpersistence services for Person model objects

PersonForm.java Intermediate object used by the Struts framework duringform processing and population

ShowPeople.jsp JSP page that fetches and displays a list of Personobjects

EditPerson.jsp JSP page displaying an HTML form allowing the creationand update of Person objects

ShowPeopleAction.java Action class used as a controller component for theShowPeople.jsp page to populate a form bean andtransfer to edit page

EditPersonAction.java Action class used as a controller component for theEditPerson.jsp page to process form submissions, applychanges to the model objects, and handle errors

ApplicationResources Properties file containing messages used in Action .properties classes or other message-display tags in Struts

struts-config.xml Configuration file defining all form beans and actions inthe Web application

Comparing Candidate Web Application Architectures 31

28128X WS.4 7/28/03 12:48 PM Page 31

Page 32: Comparing Candidate Web Application Architectures · 2003. 8. 7. · Let’s dive in to the specific presentation-tier implementations by examining the low-tech JSP-centric approach

The benefits of the Struts-based servlet-centric approach include the following:

■■ Display logic, processing logic, and form validation are encapsulated indifferent components, improving application flexibility and reuse.

■■ Pure Java code in controller components is easier to develop with IDE toolsthan action JSP pages.

■■ Navigation information is external to the components and code, improvingflexibility and reuse.

■■ Developers can be found with experience using the Struts framework, jump-starting your development effort.

Drawbacks of this approach include the following:

■■ The learning curve is steeper due to additional components and files requiredfor operation.

■■ Dependence on an open-source framework such as Struts may become an issuein the long term.

We recommend the servlet-centric architecture for medium-sized to large Webapplications, especially if they require flexible organization and have a substantialpotential for component reuse. Using a prebuilt framework such as Struts helps reducethe development effort and complexity of the application and is important in long-term maintenance.

BEST PRACTIC E Favor the servlet-centric approach for medium-sized tolarge projects unless there are strong arguments related to complexity or thelearning curve. The flexibility and reuse benefits of a servlet-centric approachalmost always exceed the costs of learning and adopting the architecture for allbut the simplest projects.

32 Bonus Chapter

28128X WS.4 7/28/03 12:48 PM Page 32