Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Apache Struts - From Novice To Professional (2006)

.pdf
Скачиваний:
56
Добавлен:
17.08.2013
Размер:
11.68 Mб
Скачать

58

C H A P T E R 6 S I M P L E V A L I D A T I O N

new ActionMessage("reg.error.password.mismatch")

For one thing, it’s obvious that we’re not passing in the actual error message! Instead, we’re passing in a key to an error message, stored in a properties file accessible to Struts.

Note Exactly how Struts locates this properties file is the subject of Chapter 9, where you’ll learn how to configure Struts.

Properties files are just text files, which contain key/value pairs. In this case, the key is reg.error.password.mismatch, and the value might be The passwords you keyed in don't match!.

Listing 6-3 shows a possible properties file for the Registration webapp.

Listing 6-3. registration.properties, a Properties File for the Registration Webapp

#Properties file for Registration webapp

#Error messages:

reg.error.userid.missing=The user id is missing. reg.error.userid.exists = The user id exists. Choose another. reg.error.userid.bad = Use only alphanumerics for the userid.

reg.error.password.mismatch = The passwords you keyed in don't match! reg.error.password.long = The password is too long! reg.error.password.short = The password is too short!

# Prompts:

reg.prompt.userid=User ID reg.prompt.password=Password

reg.prompt.password.confirmation=Password Confirmation

In Listing 6-3, you can see how error message keys are associated with the actual error messages. You can also see how prompts that go into the user interface can be stored in the properties file. Essentially, using properties files is a simple, general-purpose way to store static key/value pairs for any Java application.

C H A P T E R 6 S I M P L E V A L I D A T I O N

59

Note The dotted notation for the property keys (e.g., reg.error.userid.bad) is just a convention. This convention is useful because it forms a namespace for your properties files. If you had two or more properties files, following this convention would prevent you (or your development team) from using the same key twice. The convention is also useful because it gives you an idea of what the key might refer to.

The string argument of the ActionMessage constructor must be a key on a properties file. This might seem restrictive, but there’s a very good reason for this. This is how Struts makes it easy to localize an application.

For example, if you wanted a German version of the Registration webapp, all you’d have to do would be hand over this properties file (registration.properties) for translation. You’d save the translated version as registration_de.properties, and bundle it with your webapp. German users would see the German version of the Registration webapp and everyone else would see the default English version. Localizing a webapp was never so easy! We’ll see this in action further down the road in Chapter 12.

Note The use of properties files also makes your webapp more consistent, since it lessens your chances of displaying “Your user ID is bad” in one error message and “Your user ID isn’t valid” for the same error in a different form.

But ActionMessages are only one half of the puzzle of how error messages are displayed. The other crucial bit is the key under which the ActionMessage is stored on the

ActionErrors instance. With reference to Listing 6-1:

errors.add("password", new ActionMessage(...));

As you might guess, the key corresponds to the name of the form property associated with the error. This is only a helpful convention, not a necessity. Struts uses a special Struts tag called <errors> with an attribute called property that you match with the error key, like so:

<html:errors property="password"/>

You’d place this tag on the JSP containing the form, near the password field. I’ll go into this in more detail in Chapter 8, when I describe the View components of Struts.

Figure 6-2 summarizes the relationship between ActionErrors, ActionMessage, properties files, error keys, and the error tag.

60

C H A P T E R 6 S I M P L E V A L I D A T I O N

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 6-2. How ActionErrors ties error messages to the View component

To summarize, when the user submits a form, Struts calls validate() on the associated ActionForm subclass, which returns an ActionErrors instance. This is just a collection

of ActionMessages, each of which references error messages stored in properties files. When Struts redisplays the page, it uses special <errors> tags you’ve embedded on the page to locate exactly where to display the error messages. The <errors> tags on the page are distinguished by their property attribute, which forms the link between the tag and a particular ActionMessage instance stored on the ActionErrors collection.

That’s quite a lot to take in one go! You might want to try the quiz that follows to see if you’ve really understood the preceding material.

Simple Validation Quiz

Q1: Suppose validating a certain field requires a numerical calculation. Would this qualify as a simple validation? You should give clear reasons for your answer.

Q2: When is validate() called? Before Struts populates the ActionForm or after?

Q3: If validate() returns an empty ActionErrors instance, will the form be redisplayed?

Q4: Rewrite Listing 6-1 so that Struts only displays the error message for the first validation error encountered.

Q5: If you changed the name of one of a form’s properties (say zipcode to postcode), would you have to change the corresponding error key for ActionErrors, that is, errors.add("zipcode",...) to errors.add("postcode",...)?

Q6: If your answer to Q5 was yes, what other changes would you have to make?

Q7: If there were more than one validation error for a single property, which error message (if any) do you think would be displayed?

C H A P T E R 6 S I M P L E V A L I D A T I O N

61

Check your answers with those in Appendix D. Once you’re confident of the material, try out Lab 6.

Lab 6: ContactForm for LILLDEP

LILLDEP (Little Data Entry Program) is a webapp that maintains a database of contacts. Each contact has the following 14 properties:

name of contact

designation of contact (e.g., “Senior Engineer”)

department

email address

tel number

fax number

company to which contact belongs to

address of contact’s company

postcode of company address (“zip code” in the United States)

country of company site

website of contact’s company

activity engaged in by contact’s company

classification of contact’s company

memo, which contains miscellaneous notes for this contact Figure 6-3 shows the form data as it is seen by a user.

62

C H A P T E R 6 S I M P L E V A L I D A T I O N

Figure 6-3. The LILLDEP start page

The associated ActionForm subclass that handles validation for this contact data is called ContactForm. In this lab, you’ll complete the implementation for ContactForm. There are three things you will need to do:

Put in the getXXX and setXXX functions corresponding to each of the 14 properties.

Complete the validate() function.

Complete the implementation of a reset() function, which resets the values of the

ContactForm.

Complete this lab by following these steps.

Step 1: Prepare the Development Environment and Scripts

1.Copy the lilldep.zip file from the Source Code section of the Apress website, found at http://www.apress.com, into the Struts directory you created in Lab 4.

2.Unzip the contents, making sure you’ve preserved the directory structure.

3.You should see a subdirectory called .\Struts\lilldep\.

4.Open .\Struts\lilldep\compile.bat in a text editor and amend the PATH environment variable so that it points to your JDK installation.

C H A P T E R 6 S I M P L E V A L I D A T I O N

63

Note On Windows XP, ME, or 2000, which have built-in unzipping capabilities, the zip file may add an extra lilldep directory in the unzipped path. So, the compile.bat file’s path would be .\Struts\lill dep\lilldep\compile.bat. You could move the lilldep folder up or just continue. The compile scripts should work regardless.

Test your changes by clicking on compile.bat. You should get no errors, and you should see a file called lilldep.war in .\Struts\lilldep\.

In what follows, I’ll refer to all paths relative to .\Struts\lilldep\.

Step 2: Implement Getters and Setters for ContactForm

A skeleton for ContactForm has been created for you, in the directory net\thinksquared\ lilldep\struts.

Now, unlike the example with the Registration webapp (Listing 6-1) where the form data was stored in private variables such as _userid and _pwd, the getters and setters of ContactForm must store data in a bean called Contact.

Note The Contact bean was autogenerated using Lisptorq. If you’d like details on how it and other Model classes were created, refer to Appendix A.

The Contact bean also contains getters and setters for each of the 14 properties listed earlier. Your getters/setters for ContactForm should call the corresponding getters/setters for the Contact bean contained in ContactForm. This may seem a little strange, but this simplifies the code in later lab sessions.

Complete the following steps:

1.Put in the getters and setters for ContactForm.

2.Put in an extra pair of functions, getContact() and setContact(), to get and set the Contact bean instance.

3.Run compile.bat to ensure you have no errors.

Step 3: Implement validate()

You need to implement a few validations:

64

C H A P T E R 6 S I M P L E V A L I D A T I O N

1.Ensure that the company name isn’t blank. The error key is lilldep.error.company.

2.Ensure that the contact’s name isn’t blank. The error key is lilldep.error.name.

3.Ensure that the email address, if not blank, is a valid email address. The error key is lilldep.error.email.

Check that your work compiles without errors.

These are only a few possible validations you might in reality run on ContactForm. In Chapter 15, you’ll see how to write simple validations without having to use Java.

Step 4: Implement reset()

In addition to validate(), ActionForm exposes another function, called reset(), which resets the ActionForm’s values to defaults you define. reset() can be called by View code using a Reset button.

The skeleton for this function is in ContactForm. Complete the implementation to reset the properties of the Contact bean. (Hint: You should peruse the source code for Contact to find a suitable function that does this.)

As usual, compile your code to ensure that it’s free of errors.

What Has Struts Done for You Today?

Just as in life, “counting your blessings” often puts your problems in perspective, so it may be helpful to consider what Struts has done thus far to make writing web applications easier:

Automatically transfers form data into your app: When the user submits a form, the data is automatically read from the form and put into your ActionForm subclass. Struts even performs type castings for you.

Centralizes simple validations: All your simple validations go into the validate() function. It can’t get any simpler. Well, it can, as you’ll see in Chapter 15.

Automatically redisplays badly filled forms with errors messages: Without Struts, you had to do this yourself. Consider for a few moments how you might do this yourself without Struts. I hope you can see this is a very big plus!

Enables easy localization of error messages: This occurs through the use of properties files.

C H A P T E R 6 S I M P L E V A L I D A T I O N

65

Summary

ActionForm is the central class that for simple validation.

Your ActionForm subclass must have getters and setters for each form property, and must override validate() to run simple validations.

ActionErrors is the return value of validate() and holds error messages.

Individual error messages are represented by instances of ActionMessage.

The actual error message is stored in properties files.

C H A P T E R 7

■ ■ ■

Processing Business Logic

In the previous chapter, you learned how to run simple validations on user input. Within the Struts framework (or any sensible framework, really), only after all simple validations pass is the data ready to be processed by the system. This processing, usually referred to as “business logic,” consists of three broad tasks:

Complex validations: These are further validations that need to be run but, unlike simple validations, are not generic. They require domain-specific processing, or communication with the Model components of your webapp.

Data transformations: This includes making calculations, saving data, and preparing data for output. This is the meat of a particular task.

Navigation: This involves deciding what page to display next to the user at the completion of the task.

Struts centralizes these three tasks in a single Controller class called Action.

1,2,3 Action!

Just as simple validation was performed by your subclass of ActionForm, the processing of business logic is done by your subclass of

org.apache.struts.action.Action.

Within the MVC paradigm, your Action subclass is a Controller (see Chapter 5, Figure 5-5), because it communicates with both the Model and View components of your webapp through well-defined interfaces.

The input data upon which your Action subclass acts is the form data submitted by the user. As you’ll recall from the previous chapter, form data submitted by the user is automatically transferred by Struts to your ActionForm subclass. This ActionForm subclass instance contains the input data for your subclass of Action. The ActionForm subclass is a JavaBean, meaning it has getXXX() and setXXX() functions corresponding to each property

67