When building web applications, many of the tasks to retrieve and process requests are quite repetitive. Like any good framework, Struts places most of this tedious functionality into utility classes, so it can be shared and used by many different components and applications. This separation of utilitarian functionality from regular application-specific functionality allows for greater reuse and less redundancy throughout the framework and within your applications.
The utility classes used by Struts are located in several packages. Many of the utility components were so generic and beneficial to so many applications that they have been moved out of the Struts framework and into the larger Jakarta Commons project. These packages include BeanUtils, Collections, and the Digester component mentioned in Chapter 3.
One of the Java packages that remain in the Struts package hierarchy is org.apache.struts.util. Everything from the MessageResources class to StrutsValidatorUtil (part of the new Validator component added to the core framework in 1.1) is part of this package. This package contains many classes with different purposes and responsibilities. Although the Struts framework classes have strong dependencies on the utility classes, utility classes generally should have dependencies only on other utility classes and framework components that are lower in the food chain. This is mostly true in the Struts framework, with a few minor exceptions.
The utility classes within the util package assist the rest of the framework in solving mundane problems that all web applications encounter. We will not cover all of the classes in the package, but instead will highlight some of the more useful components.
The org.apache.struts.util.RequestUtils class provides general-purpose utility methods that are common when processing a servlet request within Struts. You've already seen several examples that use the RequestUtils class. One of the most important, and the first to be invoked for a request, is the selectApplication( ) method that is called by the ActionServlet when a new request arrives. Every method in the RequestUtils class is designed to be thread-safe and doesn't declare any instance variables. In fact, every method in the class also is static.
You seldom need to modify any of the methods within the RequestUtils class. However, you should become familiar with the methods implemented by the RequestUtils class, so you don't replicate that same behavior in your application. Another reason to be familiar with the methods is that it will help you understand what the entire framework is doing on your behalf.
The purpose of the org.apache.struts.util.ResponseUtils class is similar to that of the RequestUtils class except that it aids in building a response rather than handling a request.
There are only a few methods within the class, but the JSP tag libraries included with Struts use them extensively for filtering and writing data destined for the response object.
The org.apache.commons.beanutils package contains several classes that are used throughout the Struts framework. From the standpoint of the Struts framework, the two most important are the BeanUtils and PropertyUtils classes.
The BeanUtils class is used with JavaBeans. Struts components primarily use just three of the methods in the BeanUtils class:
populate( )
Fills a JavaBean with data, using a map of key/value pairs. The method signature for the populate( ) method is shown here:
public static void populate( Object bean, Map properties )
throws IllegalAccessException, InvocationTargetException;
getProperty( )
Returns a String representation of the property stored in the variable with the name that matches the value of the name parameter. Here is the method signature for the getProperty( ) method:
public static String getProperty( Object bean, String name )
throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException;
Regardless of the type of property that the name argument references, it will be converted and returned as a String.
getArrayProperty( )
Returns the value of the specified array property of the specified bean as a String array. Here is the method signature for the getArrayProperty( ) method:
public static String[] getArrayProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException;
Although the Java language provides reflection and introspection as part of its core APIs, the BeanUtils class provides convenience wrappers around these APIs.
The other class the Struts framework uses is PropertyUtils . Only the getProperty( ) method of this class currently is used. The getProperty( ) method in the PropertyUtils class returns the value of the specified property, without attempting to convert the type. Here is its method signature:
public static Object getProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
Much of the code in the PropertyUtils class originally was implemented in the BeanUtils class. It was moved to its own class because BeanUtils was becoming so large.
Although Java 1.3 added the much-requested and needed Collection classes, a few holes were left unfilled by the new additions. The classes within the Commons Collection package address these remaining deficiencies.
Among the features of the Collection package are:
· Implementations of Lists and Maps that are designed for fast access
· Methods to utilize set-theory properties of collections, such as unions, intersections, and the closure properties
· Adaptor classes that allow conversions between Java 1.1 containers and Java 1.2-style containers
Currently, the Struts framework uses only the FastHashMap class from the Collection package. The FastHashMap class is designed to operate in a multithreaded environment, where most of the calls are read-only. The FastHashMap extends java.util.HashMap and provides two different modes, slow and fast. In slow mode, all access is synchronized. This is appropriate for when initialization is taking place. Once initialization is complete and mostly read-only calls occur, the Map can be switched to fast mode by calling setFast(true). In fast mode, read access is not synchronized, and write calls use cloning for performance.
Action classes, if designed and scoped properly, can perform some very important functionality for an application. To prevent unauthorized users from finding a way to execute an action, Action classes should have a way to authorize certain users to perform the intended action. The processRoles( ) method is designed to check whether any roles are defined in the configuration file for the Action and, if so, to call the isUserInRole( ) method on the request. The problem with this approach is that not all applications can define their roles ahead of time. In some applications, roles can be added and removed dynamically and can be enumerated beforehand. In this case, there must be an alternative approach to dealing with users, roles, and permissions—container-managed security might not be enough, and an application might have to handle more of the details programmatically.