7.3 Using ActionErrors

Earlier in this chapter in Example 7-2, we saw that the validate() method returns an ActionErrors object. The ActionErrors class encapsulates one or more errors that have been discovered by the application. Each problem discovered is represented by an instance of org.apache.struts.action.ActionError.

It should be pointed out that in Example 7-2, instances of the ActionMessage class and not ActionError were added to the ActionErrors collection. ActionMessage is actually the parent of ActionError. We will talk more about the usage of the ActionMessage class in the next section. For now, when you see ActionError mentioned, just know that you can substitute ActionMessage in most cases.

An ActionErrors object has request scope. Once an instance is created and populated by the validate( ) method, it is stored into the request. Later, the JSP page can retrieve the object from the request and use the ActionError objects contained within it to display error messages to the user.

The Struts framework includes several JSP custom tags that make retrieving and displaying the messages very easy. Two of them, ErrorsTag and MessagesTag, are discussed in Chapter 8.

An instance of ActionErrors can be instantiated in the validate() method and populated by adding instances of the ActionMessage class to it. The LoginForm from Example 7-2 demonstrated this and is illustrated again here for convenience:

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request){   ActionErrors errors = new ActionErrors( );   if( getEmail( ) == null || getEmail( ).length( ) < 1 ){     errors.add("email", new ActionMessage("security.error.email.required"));   }   if( getPassword( ) == null || getPassword( ).length( ) < 1 ){     errors.add("password", new ActionMessage("security.error.password.required"));   }   return errors; }

The validate() method in this fragment checks to make sure that the email and password fields have been set with values other than an empty string. If not, ActionMessage objects are added to the ActionErrors instance.

The ActionMessage class contains several useful constructors; a few are listed here:

public ActionError(String key); public ActionError(String key, Object value0); public ActionError(String key, Object value0, Object value1); public ActionError(String key, Object[] values);

The key argument is a String value that corresponds to a key from one of the application's resource bundles. The custom tags MessagesTag and ErrorsTag use this value to look up the message to display to the user. The remaining arguments are used as parametric replacement values for the message. For example, if you had a bundle message defined like this:

global.error.login.requiredfield=The {0} field is required for login

you could create an instance of an ActionMessage like this:

ActionMessage message = new ActionMessage("global.error.login.requiredfield", "Email");

The message displayed to the user after substituting in the "Email" string would be:

The Email field is required for login

If building I18N applications is a requirement for you, you must be careful when using hardcoded String values, as in the previous example. The string "Email" can't easily be localized, because it's hardcoded into the source code.

In this case, you should get the localized value from the bundle as well before passing it as an argument in the ActionMessage constructor.

When adding instances of the ActionMessage class to the ActionErrors object, the first argument in the add() method is a property that can be used to retrieve a specific ActionMessage instance. For example, if you have a login input field and a password field and you want to display a particular message next to each corresponding field, you could do:

errors.add("login",            new ActionMessage("security.error.login.required")); errors.add("password",            new ActionMessage ("security.error.password.required"));

By associating a specific name with each error, you can retrieve the respective error in the JSP page using the MessagesTag tag, which we'll discuss in the next chapter.

If instead you want to show all of the errors at the top of the page, you can use the constant ActionMessages.GLOBAL_MESSAGE, like this:

errors.add(ActionMessages.GLOBAL_MESSAGE,            new ActionMessage("security.error.password.required"));

7.3.1 The ActionMessage Class

In Struts 1.1, a new message class was added that also can be used to display messages to a user. The org.apache.struts.action.ActionMessage class operates in the same manner that the ActionError class does in fact, it was added as the superclass to the ActionError class.

The main reason that the ActionMessage class was added to the framework was that the name ActionError implies that it shouldn't be used for general-purpose informational or warning messages, although it is used that way by many developers. A more general-purpose message class made sense.

The ActionMessage is used exactly like the ActionError class, except that it can represent a less severe message that needs to be displayed to the user. Instances of this class are created the same way and added to an ActionMessages object instead of an ActionErrors object. Because ActionError is just a specialized message, it extends the ActionMessage class. Figure 7-5 illustrates the relationship between these classes.

Figure 7-5. ActionErrors are specialized ActionMessages

Starting with Struts 1.2, you should expect the ActionError class to be deprecated. You should make all attempts to start using the ActionMessage class instead. The ActionErrors class will a little harder for the Struts developers to remove as it is tied into the framework quite tightly. Nonetheless, the writing is on the wall and you may eventually be using ActionMessages exclusively.

7.3.2 Creating ActionErrors in the Action Class

The ActionForm is not the only place that you can create ActionMessages or ActionErrors. You also can create them in other parts of the framework. If, for example, a business operation called from an Action raised an exception and you wanted to insert an error message informing the user, you could create an ActionMessage from the Action class itself. The Struts Action class includes functionality to support this.

When the business operation throws the exception, the Action class catches it and takes the appropriate steps usually returning to the previous page and displaying an error message to the user. Returning to the previous state can be accomplished by returning the appropriate ActionForward, but the ActionMessage needs to be put in the request before the forward occurs.

In Chapter 10, you'll learn how to take advantage of the declarative exception handling in Struts 1.1 and thus avoid having to deal with the exceptions in the Action class completely.

Example 7-4 illustrates how to put the ActionMessage into the request using the LoginAction class.

Example 7-4. Creating ActionErrors from the execute( ) method
public ActionForward execute( ActionMapping mapping,                               ActionForm form,                               HttpServletRequest request,                               HttpServletResponse response )   throws Exception{     /**      * Get the user's email and password, which should already have been      * validated by the ActionForm.      */     String email = ((LoginForm)form).getEmail( );     String password = ((LoginForm)form).getPassword( );     // Log in through the security service     IStorefrontService serviceImpl = getStorefrontService( );     UserView userView = null;     try{        userView = serviceImpl.authenticate(email, password);     }catch( InvalidLoginException ex ){       ActionMessages messages = new ActionMessages( );       ActionMessage newMessage = new ActionMessage ( "security.login.failed" );       messages.add(ActionMessages.GLOBAL_MESSAGE, newMessage);       saveMessages( request, messages );       // Return back to the previous state       return mapping.findForward( mapping.getInput( ) );     }     // Authenticate was successful     UserContainer existingContainer = null;     HttpSession session = request.getSession(false);     if ( session != null ){       existingContainer = getUserContainer(request);       session.invalidate( );     }else{       existingContainer = new UserContainer( );     }     // Create a new session for the user     session = request.getSession(true);     existingContainer.setUserView(userView);     session.setAttribute(IConstants.USER_CONTAINER_KEY, existingContainer);     return mapping.findForward(IConstants.SUCCESS_KEY);   }

In Example 7-4, when an InvalidLoginException is thrown by the authenticate() method, the exception is caught and an ActionMessage is created. The saveMessages() method exists in the Struts base Action class and stores the ActionMessages object into the request.

Once the ActionError or ActionMessage is stored in the request and control is forwarded to a JSP page, one of the framework's JSP custom tags can be used to print out the messages to the user. These tags are discussed in the next chapter.

Programming Jakarta Struts
Programming Jakarta Struts, 2nd Edition
ISBN: 0596006519
EAN: 2147483647
Year: 2003
Pages: 180

Similar book on Amazon

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