Monday, August 4, 2008

Error Keys and ApplicationResources - Handling Errors in a Struts Application using Rational Application Developer / IRAD and WebSphere

Error Keys and ApplicationResources

When an ActionError is created, you probably noticed that it is associated with two text Strings, the first one typically being the name of the field you are validating, and a second ‘dot separated’ text string that describes the error in some mysterious pseudo language.

These error Strings, also known as a message keys, such as error.language.case and error.language.unsupported are supposed to map to message strings in the ApplicationResources.properties file.

When the Struts framework is asked to output a message associated with an error, it uses this message key, finds the actual message associated with this message key in the ApplicationResources.properties file, and then prints out the associated message.

The ApplicationResources.properties file includes entries such as:

error.language.case = Use at least one upper case letter

error.language.unsupported = Enter a supported language

So, when an a user enters an unsupported language, they get an italicized message indicating that their language isn’t supported.


Editing the ApplicationResources File

1. In the Navigator view of the Web perspective, open the PulpJavaWeb project.

2. Drill down under the ‘Java Resources’ folder and open the com.ibm.pulpjavaweb.resources package

3. Double-click on the ApplicationResources.properties file to open up the associated editor

4. Add the error keys used in the validate method of the LanguageForm

Associate your error keys with an appropriate error message

error.language.case =Start your language with an upper case letter

error.language.unsupported=You entered and unsupported language

5. Uncomment the header and footer line for the tag by removing the # sign next to errors.header and errors.footer

6. Click File à Save All or CTRL+S to save your changes


Providing Feeback to You Users

Currently, when validation of user data fails, we simply send the user to a page that informs them that they are in idiot. However, it would be nice to use the message keys and associated messages to provide dynamic feedback to the user. You’ll be amazed how easy it is to do this

1. Navigate to the ‘Project Navigator’ view of the Web perspective

2. Find the badlanguage.jsp file under the PulpJavaWeb \ WebContent directory

3. Double-click on the badlanguage.jsp file to bring up the associated WYSIWYG editor, aka ‘Page Designer’

4. In the Design view of the html editor, right-click anywhere on the page and select ‘Page Properties’

5. Move to the ‘JSP Tags’ tab of the ‘Page Properties’ window and make sure the struts-html.tld exists as a taglib directive. Click ‘OK’ to return to ‘Page Designer’

6. On the Design view of the html editor, click to a point where you want error messages to display.

7. From the menu bar, select JSP à Instert Custom…

8. From the ‘Instert Custom Tag’ wizard, higlight the struts-html.tld reference in the left pane, and select the errors tag in the right hand pane.

9. Click ‘Insert’ and then ‘Close’ to return to ‘Page Designer’

10. A list of error messages will appear where you inserted your custom tag. This will translate into actual error messages from the ApplicationResources file at runtime.

11. Stop and start your test server, and then test your application with good and bad data.

When bad data is entered, you should see the error messages that are entered in your ApplicationResources.properties file



http://www.scja.com/javatutorials/strutsrt.html

Hibernate Tutorials

Sun Certified Java Associate Mock Exams and Tutorials

Advanced Form Handing in Struts with IBM Rational Application Developer IRAD/WSAD for WebSphere Application Server and Portal Server

Form Handling

Form Handling

The problem with taking input from a luser is that they are incompetent. We can tell a user to enter "French, English or Spanish" in the textfield, but the user might misspell their language, not enter in an uppercase first letter, or even enter in just the first letter of their preferred language.

http://www.scja.com/javatutorials/strutsrt.html

Hibernate Tutorials

Sun Certified Java Associate Mock Exams and Tutorials

Right now, all data, which includes good data and bad data, is getting sent to our TryLingualAction class.

Polluting our TryLingualAction class with bad data slows things down for the few competent users that actually provide valid data. It would be nice to have a special component that could filter out bad data, while allowing good data to be passed on to our action class.

Of course, we could do validation in our Action class, but that’s not what Action classes are designed for.

Our Action class should really be concerned with acting as a controller, which means delegating to JavaBeans and EJBs to implement business logic, and then forwarding to and appropriate JSP page to generate markup for the client. Validation is an important and cumbersome task we would prefer to keep out of our Action classes.

Well, say hello to the ActionForm.

The ActionForm acts as a data filter. An ActionForm gets associated with an actual Action object, and the ActionServlet calls the validate method of an ActionForm before invoking the execute method of an Action object. If the validation fails, the user is sent to an error page. If validation is successful, the request is forwarded to the corresponding Action class.

To use an ActionForm, you simply subclass the Struts ActionForm class and add instance variables for every input field on the html form you wish to validate.

The instance variables in your ActionForm must match the name of the textfield in the html form. Yes, this means you'll have to communicate with your web developer.

Secondly, all instance variables must be of type String. That's how they come to the server, so that's how they are declared in you ActionForm.

From there, you add a setter and getter method for each instance variables in the ActionForm, and behind the scenes, the Struts framework takes care of matching the data a user typed into a form with the matching fields in your ActionForm.

The next step in creating an ActionForm is adding a validate method.

In the validate method, you simply test all of the data that the user has sent to the server. If the user is supposed give you a number, then do a parseInt on the variable and see if it throws a NumberFormatException. If the variable must start with an uppercase letter, you use methods in the String class to verify that it does.

The return type of the validate method is a special Struts component called ActionErrors. The ActionErrors (plural) object is a collection class that contains ActionError (singular) objects

The idea is, if any of your validations fail, you create an ActionError object, and add that ActionError to the ActionErrors collection.

The validate method of the ActionForm actually returns an instance of the ActionErrors object. If the returned ActionErrors object is empty, execution continues to the associated action object and the data is considered to be valid. If there are errors in the ActionErrors object, validation is considered to have failed and a users is directed to an error page.

We will create an ActionForm to validate the data a user enters into the language textfield in our html form.


Creating ActionForms

1. From the Web perspective, open the PulpJavaWeb project and right click on the Java Resources folder.

2. From the context menu that appears, select New à Other

3. Open the Web branch on the left pane of the ‘New Resource Wizard’ and then highlight the ‘Struts’ leaf.

4. On the right pane, click on ActionForm Class and select ‘Next >’

5. On the ActionForm Wizard, enter LanguageForm as the class name.

6. Make the package name: com.pulpjava.forms

7. Accept the options to add a reset, validate and inherited methods. Make sure the selected methods use the HttpServletRequest object

8. Click the ‘Next >’ button to continue

The following page asks you which form elements you are interested in validating. This kewl wizard makes it incredibly easy to create ActionForms

9. Open the directory tree and drill down until you fing your language.html file and the subsequent form that calls tryLingual.do

10. Add a check in the box indicating that you want to validate the language textfield

11. Click ‘Finish’ to create the ActionForm

The ActionForm should open in the Java editor.


package com.pulpjava.forms;

import javax.servlet.http.*;

import org.apache.struts.action.*;

public class LanguageForm extends ActionForm {

private String language = null;

public String getLanguage() {

return language;

}

public void setLanguage(String l) {

this.language = l;

}

public void reset(ActionMapping mapping,

HttpServletRequest request) {

language = null;

}

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {

ActionErrors errors = new ActionErrors();

return errors;

}

}


Coding the validate Method of the ActionForm

public ActionErrors validate(

ActionMapping mapping,

HttpServletRequest request) {

ActionErrors errors = new ActionErrors();

if (!Character.isUpperCase(language.charAt(0))){

errors.add("language",

new ActionError("error.language.case"));

}

if ((!language.equals("French"))

&& (!language.equals("English"))

&&(!language.equals("Spanish"))) {

errors.add("language",

new ActionError("error.language.unsupported"));

}

return errors;

}


Debriefing the Validate Method

By time the validate method is triggered on the server, the language variable has already been initialized with the value the user typed into the textfield on the form. The Struts framework does this initialization for you.

The purpose of the validate method is to verify the validity of the data sent to the server from the user. In our validate method, we do two simple validations

The first validation is to make sure the first letter is indeed uppercase. If the first letter is not capitalized, we create an ActionError associated with the error code “error.language.case” We then add this ActionError (singular) to our ActionErrors (plural) collection.

A second validation checks to ensure that the user has entered in either English, Spanish or French. If not, a new ActionError is created with the error code “error.language.unsupported” and added to our our ActionErrors collection.

At the end of the method, the ActionErrors instance, named errors, is returned. If no instances of the ActionError class are in the ActionErrors collection, then the associated Action class is invoked. If the ActionErrors collection contains one or more errors, the user is redirected to an error page.


Using the ActionForm in an Action

If you look at the execute method of the Action class, you’ll notice that an instance of an ActionForm is passed into the method along with the request, response and mapping object. If you have associated your action object with a form, the form passed in is actually that associated form.

We can take the form passed into the validate method and cast it into a LanguageForm. We can then obtain the language by using the getLanguage() method of the form, rather than going through the getParameter() method of the request.

Going through the form is not only simple, although an extra cast is required, but it also eliminated potential runtime exceptions caused by incorrect Strings being supplied to the getParameter() method.


Let’s change our TryLingualAction class to use the LanguageForm rather than going through the HttpServletRequest to obtain user input.

1. From the ‘Project Navigator’ view of the Web Perspective, find and double-click on your TryLingualAction.java file

2. Comment out the line that obtains the users language using the getParameter(“language”) method of the request method.

//String language = request.getParameter("language");

3. Add the following two lines after the code you commented out:

LanguageForm languageForm = (LanguageForm)form;

String language = languageForm.getLanguage();

This code first casts the form passed into the method into our own LanguageForm. It then grabs the language from this form.

Referencing the LanguageForm will generate an error, due to the fact that it is defined in a separate package.

4. Add an import for the LanguageForm by right-clicking on your source code and selecting Source à Organize Imports

While the import error has been corrected, the WSAD may still indicate there is an error.

5. Do a File à Save All to save your changes and eliminate the import error


Associating an Action with an ActionForm

1. Open to the Web perspective Window à Open Perspective à Web

2. From the ‘Project Navigator’ view, drill down to the struts-config.xml file, which sits under the PulpJavaWeb \ WebContent \ WEB-INF directory

3. Open the struts-config.xml file by double clicking on it. The associated editor will open.

4. In the struts-config.xml editor, highlight the /tryLingual action

5. Associate the tryLingual action with the LanguageForm by clicking the dropdown box for ‘Form Bean Name’ under the ‘Form Bean Specification’ section of the ‘Action Mapping’ tab of the struts-config editor and selecting languageForm

6. Specify the error page to forward the user to by entering ‘badlanguage.jsp’ as the Input parameter

If the validate method fails, the user will be forwarded to the page specified by the Input parameter.

You can read the page as “call the tryLingual action, but filter the data first using the languageForm, and if there is bad date, get new input from the user by sending them to the badlanguage.jsp page.

7. Save your changes by clicking File à Save All.

Do a File à Close All as well to make sure all editors are closed.

8. Add the badlanguage.jsp page by right-clicking on the WebContent folder in the Project Navigator view and selecting New à JSP File

9. Name the JSP file badlanguage.jsp and click ‘Finish’

10. Using the WYSIWYG editor, add a witty error message in the badlanguage.jsp

11. Because you have changed the struts-config.xml file, you must restart your server before your changes will take effect.

12. Right click on your language.html file and select ‘Run on Server’ and test your application with good and bad data.