Package org.apache.struts.util

The Utilities package provides a variety of families of classes, to solve problems that are commonly encountered in building web applications.

See:
          Description

Class Summary
ArrayStack Implementation of the java.util.Stack API that is based on an ArrayList rather than a Vector.
BeanUtils Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Beanutils package.
ConvertUtils Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Beanutils package.
ErrorMessages Deprecated. Use org.apache.struts.action.ActionErrors instead
FastArrayList Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Collections package.
FastHashMap Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Collections package.
FastTreeMap Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Collections package.
GenericConnection Generic wrapper implementation of a Connection that works with GenericDataSource to wrap connections for any JDBC driver.
GenericDataSource Generic data source implementation of the DataSource interface.
IteratorAdapter Utility method for converting Enumeration to an Iterator class.
MessageResources General purpose abstract class that describes an API for retrieving Locale-sensitive messages from underlying resource locations of an unspecified design, and optionally utilizing the MessageFormat class to produce internationalized messages with parametric replacement.
MessageResourcesFactory Factory for MessageResources instances.
PropertyMessageResources Concrete subclass of MessageResources that reads message keys and corresponding strings from named property resources in the same manner that java.util.PropertyResourceBundle does.
PropertyMessageResourcesFactory Factory for PropertyMessageResources instances.
PropertyUtils Deprecated. At some point after Struts 1.0 final, will be replaced by an equivalent class in the Jakarta Commons Beanutils package.
RequestUtils General purpose utility methods related to processing a servlet request in the Struts controller framework.
ResponseUtils General purpose utility methods related to generating a servlet response in the Struts controller framework.
ServletContextWriter A PrintWriter implementation that uses the logging facilities of a javax.servlet.ServletContext to output its results.
 

Package org.apache.struts.util Description

The Utilities package provides a variety of families of classes, to solve problems that are commonly encountered in building web applications.

[Introduction] [Beans and Properties] [Collection Classes] [JDBC Connection Pool] [Message Resources]

Introduction

The Struts Utilities Package offers several families of classes that assist in solving commonly encountered problems when building web applications. Most of the classes in this package do not rely on the controller servlet framework, or the custom tag libraries, so they are also suitable for general Java application programming. The following families are included:


Beans and Properties

FIXME

FIXME some parts of this might me moved to Taglibs

The BeanUtils and PropertyUtils utilities are used through out struts including the IteratorTag, WriteTag. Much of these utilities rely on and make use of Java reflection, to manipulate Java beans . Creating a valid Java bean is essential ! Briefly referring to the example class ProductBean below would follow these rules :

        public class ProductBean() {
           private String value;
           public String getvalue() (return this.value}
           public void setvalue(String value) (this.value = value}
        }
    

Observing these conventions will avoid unnecessary errors and save time.

This makes it possible to create a JSP page such as:

        <logic:iterate id="product" name="receivedForm" property="receivedList">
              <bean:write name="product" property="description" />
              <bean:write name="product" property="value" />
        </logic:iterate>
    
In this case receiveForm is an ActionForm, with a definition such as
        public class ReceivedForm extends ActionForm  {
         private ProductList productList;
         public void setReceivedList(Enumeration enum) {
             productList = new ProductList(enum,Limits.ARRAY_SIZE_MIN);
         }
         /**
          * Defined so java.bean reflection will see getReceivedList
          * as a getter for receivedList
          */
         public void setReceivedList(ProductList productlist) {

         }

         /**
          * Returns an Array list of ProductBeans.
          */
         public ProductList getReceivedList() {
           return productList;
         };
       } //ReceiveForm

Collection Classes

Background

Version 1.2 of the Java 2 Standard Edition (J2SE) introduced a powerful set of collection classes that are generally useful in Java programming, based on the fundamental interfaces java.util.Collection, java.util.List, java.util.Map, and java.util.Set. Compared to the collection classes available in JDK 1.1 (principally java.util.Hashtable and java.util.Vector), the new classes offer much richer functionality as well as the opportunity to improve performance.

The performance increase potential comes from the fact that none of the methods used to access the new collection classes are synchronized as were the methods of Hashtable and Vector. In a single thread application, this means that method calls can execute much more quickly because synchronization is never necessary. In a multiple thread environment, though, it is up to the developer to ensure that any method calls made while another thread is modifying the collection must be synchronized.

There are many cases in multithreaded server environments (such as a web application) where data structures are initialized at application startup time, and are then predominantly accessed in a read-only manner. An example of this is the Struts controller application, which initializes its collection of ActionMapping instances (each corresponding to an <action> element in the struts-config.xml file) at startup time. However, it is legal for an application to dynamically change the set of available mappings while the application is running -- so, to be safe, it would normally be necessary to synchronize access to such collections, even though 99% of those accesses are read only and would not otherwise require synchronization.

To deal with such scenarios, the Struts utility package includes a series of specialized collection classes designed to operate in a multithread environment where the large majority of accesses are read only, without requiring synchronization on every operation, but still protecting against the possibility of runtime modifications to the underlying collection.

Theory of Operation

Each of the available collection classes operates in one of two modes: fast or slow. When first created, the collection operates in slow mode, which is appropriate for initially populating the contents of the collection. Once the initial population is complete, switch to fast mode by calling setFast(true) for maximum performance when most accesses are read-only.

When operating in slow mode, all methods that access this collection, even read-only methods, are synchronized - resulting in impacts on performance similar to that always performed by the Hashtable and Vector classes. This mode is appropriate when you are initializing the content of the collection, or when you need to perform a large series of updates.

Using fast mode, on the other hand, causes method calls to operate in the following manner:

As you can see, modification operations are much more expensive when operating in fast mode, but doing things in this way allows read only operations, which should be the vast majority, to operate at maximum speed.

If your collection will never be accessed in a multithread environment, you should use one of the standard collection classes instead, without synchronization, for maximum performance.

Available Collection Classes

The following collection classes, with the ability to operate in either fast or slow mode, are included:

JDBC Connection Pool

Background

A large number of web applications require interaction with a relational database to access or update persistently stored information. In a typical client-server application, each concurrent user opens their own database connection at program initialization, and uses this connection throughout the period of time the application is open.

While this approach can work well in an environment where the number of active users is reasonably fixed, it does not scale well to a web application where the number of simultaneous users could be very large. In addition, open database connections (even when not actively used) do impose some overhead costs, and most web application users (at a given instant) are reviewing the contents of a previously generated page (or typing in their next set of input information), rather than actively accessing the database.

To deal with this situation, several basic strategies are possible:

  1. Open a connection on each request, do whatever processing is required, and then close the connection.
  2. Open a connection for each user, and store it in the user's session.
  3. Share a "pool" of open connections between all of the application's current users.

The first strategy has the virtue of simplicity - you merely need to open a database connection any time you need one, perform the appropriate data accesses and updates, and close the connection. However, it suffers from a major disadvantage: on most databases, establishing a connection can be very time consuming (often requiring multiple seconds of clock time), in order to perform a database transaction that might take milliseconds.

Opening a connection per user, as the second strategy suggests, is similar to the approach taken with client-server applications described earlier. As long as the number of simultaneous users can be controlled at a manageable number (such as with many intranet-based applications), this approach is feasible. However, it becomes unmanageable when the number of users can climb rapidly to very large numbers (as is typical of many Internet-hosted public applications), and still requires more overhead than a strategy that would share a smaller number of connections.

Connection pooling is an implementation of the third strategy. It is based on the assumption that most users of a web application will be interacting locally with the last page that was sent to their browser. The number of users actually performing a request at any given time is usually a very small percentage of the total number of active users, and during request processing is the only time that a database connection is required.

Struts provides a simple connection pool class called org.apache.struts.util.GenericDataSource. It allows you to configure a set of connections (with identical connection parameters) to a particular database, using a particular JDBC driver, and then share those connections among a number of simultaneously operating threads (such as the various request threads that are concurrently active in a servlet container). The GenericDataSource class implements the javax.sql.DataSource interface from the Java Database Connectivity (version 2.0) Standard Extension API, so any programs you use to access it should reference this interface, rather than the class name directly. That way, you can migrate to a more advanced connection pool implementation later, with little or no impact on your application.

For more information about the JDBC 2.0 Standard Extension API, you can download the spec (and the corresponding API classes), from http://java.sun.com/products/jdbc. You can also find pointers to a substantial amount of other information about available JDBC drivers, programming tutorials, and so on, at this web address.

Initializing and Finalizing the Connection Pool

The following instructions show you how to configure the connection pool class and use it, from any Java application. As you will see below, the Struts controller servlet offers you convenient mechanisms to configure one or more connection pools, and make them available to Action classes and JSP pages by storing the connection pool instances as servlet context attributes (in JSP terms, application-scope beans).

To configure a GenericDataSource instance, you must first create one:

    GenericDataSource dataSource =
      new GenericDataSource();

Next, you must set the appropriate properties, by calling the corresponding JavaBeans property setter methods provided by this class. (See the Javadoc API for the GenericDataSource class for more details on the available properties). An example of configuring the connection pool object to a Postgres database might look like this:

    dataSource.setAutoCommit(false);
    dataSource.setDescription("My Database Connection Pool");
    dataSource.setDriverClass("org.postgresql.Driver");
    dataSource.setMaxCount(4);
    dataSource.setMinCount(1);
    dataSource.setPassword("mypassword");
    dataSource.setUrl("jdbc:postgresql://localhost/mydatabase");
    dataSource.setUser("myusername");

Finally, you must open() the connection pool. This will establish the initial connections to the database (based on the value you have configured for the minCount property). As you use connections from the pool in multiple threads, additional connections (up to the number you specify with the maxCount property) will be created as needed.

    try {
        dataSource.open();
    } catch (SQLException e) {
        ... deal with exception ...
    }

When you are completely through with the connection pool, you can gracefully close all of the currently open database connections by executing

    try {
        dataSource.close();
    } catch (SQLException e) {
        ... deal with exception ...
    }
Using the Generic Connection Pool

To access the database from within an application class, you must follow a simple four-step procedure each time you need a connection:

  1. Acquire a connection from the connection pool.
  2. Perform the database operations required by your application.
  3. Cause the last database transaction to be committed or rolled back (commits are required on many databases to ensure that the database operations you just performed are permanently stored or not).
  4. "Close" the connection, which returns it to the connection pool for reuse later.

An example code sequence that performs this procedure might look like this:

    DataSource dataSource = ... acquire reference to dataSource ...
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    try {
        conn = dataSource.getConnection();
        stmt = conn.prepareStatement("SELECT cust_id, name FROM customers" +
          " WHERE (last_purchase_date >= ?)" +
          " ORDER BY name");
        stmt.setDate(1, lastPurchaseDate);
        rs = stmt.executeQuery();
        while ((row = rs.next()) != null) {
            ... process this row ...
        }
        rs.close();
        rs = null;
        stmt.close();
        stmt = null;
        conn.commit();
        conn.close();
        conn = null;
    } catch (SQLException e) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException f) {
                ;
            }
            rs = null;
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException f) {
                ;
            }
            stmt = null;
        }
        if (conn != null) {
            try {
                conn.rollback();
            } catch (SQLException f) {
                ... deal with exception ...
            }
        }
        ... deal with exception ...
    } finally {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException f) {
                ... deal with exception ...
            }
            conn = null;
        }
    }

One aspect of the above code example that might surprise developers who have previously used JDBC connections individually is the idea of calling close() on the Connection. Normally, this call will sever the Connection's underlying link to the database, and render that Connection unuseable for any further operations. However, when used in a connection pool environment, the actual Connection you receive by calling getConnection() is a customized "wrapper" around a real JDBC Connection instance. Calling close() on this wrapper simply causes this connection to be returned to the pool.

What would happen if your application failed to return a connection to the pool when it was through? As you might expect, that particular connection becomes "lost" to the server, and can never again be used (even though it remains connected to the database throughout the life of the connection pool itself). If this happens repeatedly, you will eventually exhaust the pool of available connections, and application processing will stop.

To avoid this problem, your application logic must ensure that it ALWAYS returns allocated connections to the pool, no matter what problems might happen in the interim. The Java language provides one convenient mechanism to achieve this - using a finally block, as in the code example above. This is not the only way to ensure that a connection is always returned, but it is very convenient.

Using Connection Pools with the Struts Controller Servlet

If your application is running underneath the Struts controller servlet (org.apache.struts.action.ActionServlet), you can take advantage of the servlet's ability to preconfigure one or more connection pools for you, based on information included in the struts-config.xml file. Simply include a section that looks like this:

    <data-sources>
      <data-source>
        <set-property property="autoCommit"
                      value="false"/>
        <set-property property="description"
                      value="Example Data Source Configuration"/>
        <set-property property="driverClass"
                      value="org.postgresql.Driver"/>
        <set-property property="maxCount"
                      value="4"/>
        <set-property property="minCount"
                      value="2"/>
        <set-property property="password"
                      value="mypassword"/>
        <set-property property="url"
                      value="jdbc:postgresql://localhost/mydatabase"/>
        <set-property property="user"
                      value="myusername"/>
      </data-source>
    </data-sources>

After being initialized, the connection pools will be stored as servlet context attributes under the bean name specified by the key attribute. If you did not specify a key, the default key is the value of the string constant Action.DATA_SOURCE_KEY. Thus, you can access and utilize a connection, from within an Action class, like this (for the default data source):

    DataSource dataSource = (DataSource)
      servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);
    conn = dataSource.getConnection();
    ... perform required functions as in the previous example ...
    conn.close();

Message Resources

Background

Modern applications often include the requirement to support multiple languages, for users who prefer to interact in a language other than the default language configured on the server platform. In addition, sentences often need to be constructed, with dynamic content whose placement in the message depends on the standard sentence structure in that particular language.

The standard Java platform includes a family of classes (java.util.ResourceBundle) designed to support looking up message strings based on a standard "key". The resource bundle classes automatically access a Java class (or properties file) that is named with a naming convention that includes the Locale to which messages in that class (or file) pertain. However, this selection is based only on the default Locale of the server platform, and cannot be adjusted on a per-user basis as required for an internationalized web application.

Struts includes a family of classes (org.apache.struts.util.MessageResources) that extends the basic approach to looking up message strings by key, allowing you to optionally specify a Locale along with the key. In this way, you can build applications that let your users select which Locale they wish to operate within, and then look up messages in that language - using the same message keys no matter what language is selected.

In addition to supporting dynamic selection of a Locale for message lookup, the MessageResources family of classes optionally allow you to specify up to four parameter replacement objects, which are used to replace the parameter placeholders "{0}" through "{3}" in the retrieved message. This replacement uses the facilities of the standard Java java.text.MessageFormat class, which supports many extended formatting capabilities as well.

For more information about internationalized messages, consult the following resources in your Java Development Kit documentation bundle:

Using the Standard MessageResources Implementation

The standard MessageResources implementation provided by the Struts library uses Java properties files to initialize message strings, in a manner very similar to that supported by the java.util.PropertyResourceBundle class. The following steps are required to use these facilities in your Java application.

First, prepare a Java properties file for each language (or Locale) in which you wish to support your messages. The filenames you use must conform to the naming convention for property resource bundles, as described in the documentation referenced above. Be sure you use the same message keys in each file to identify the same message.

For example, you might prepare files in French, Spanish, and English that contain language-specific versions of the word "Hello". The French file would be named Messages_fr.properties and contain the following:

    hi=Bonjour

while the Spanish and English files would be named Messages_es.properties and Messages_en.properties respectively. The corresponding message string definitions would say hi=Hola and hi=Hello in these files.

Second, place these properties files into the class path for your application, exactly as you would with class files themselves. The name actually used to load resources will look like a fully qualified Java class name (with appropriate package prefixes), so the file should be nested inside a directory structure that matches the packaging (either in an unpacked directory, or within a JAR file, as appropriate). For example, assume you place directory "foo" on your classpath, and stored the above properties files in directory "foo/com/mycompany/mypackage". (If you were using a JAR file like "foo.jar" instead, the files would be in directory "com/mycompany/mypackage" within the JAR file).

Third, initialize a MessageResources object that corresponds to the set of properties files for a particular name, within a particular package. The easiest way to do this is to initialize a variable in your main application class, like this:

    public static MessageResources messages =
     MessageResources.getMessageResources("com.mycompany.mypackage.Messages");

Note that the "com.mycompany.mypackage" part of the name matches the package directory into which you placed your properties files, and "Messages" is the filename prefix for the particular family of properties files supported by this MessageResources instance. Depending on your development process, you might find it convenient to store all message strings for an entire application in a single properties file family, or to have several families - in Struts, for example, there is a family of properties files for each Java package.

To access a message string with a particular Locale, execute a statement like this:

    Locale locale = ... select the locale to be used ...
    String message = messages.getMessage(locale, "hi");

In this case, the variable message will contain the message string corresponding to the key "hi", in the language that corresponds to the locale that was selected.

For an example of message formatting with replaceable parameters, assume that the message strings looked like this, instead (only the English version is shown - corresponding changes would be made in the other files):

    hi=Hello {0}

Now, you can personalize the retrieved message like this:

    Locale locale = ... select the locale to be used ...
    String name = "Joe";
    String message = messages.getMessage(locale, "hi", name);

and the marker "{0}" will have been replaced by the specified name (Joe), no matter which language is in use. See the JavaDoc API documentation for the java.text.MessageFormat class for more advanced uses of the parameter replacement mechanism.

Developing Your Own MessageResources Implementation

In the above example, we were using the default MessageResources implementation supplied by Struts, which uses property files to store the message strings. It is also possible to create customized mechanisms to retrieve messages (such as loading them on demand from a database). The steps required are as follows:

A code example that illustrates this technique is:

    MessageResourcesFactory.setFactoryClass("com.mycompany.mypkg.MyFactory");
    MessageResourcesFactory factory = MessageResourcesFactory.createFactory();
    MessageResources resources =
     factory.createResources("configuration information");

Once you have created your custom MessageResources instance, you utilize it to access message strings (with or without parameter replacement objects), exactly as we illustrated with the standard implementation in the previous section.

Using MessageResources With Struts

If your application uses the Struts controller servlet, you can optionally configure Struts to load an application-specific message resources instance for you, and make it available as a servlet context attribute (in JSP terms, an application-scope bean). This mechanism is managed by setting the following servlet initialization parameters in the web application deployment descriptor:

Struts provides several JSP custom tags that assume the existence of a java.util.Locale attribute in the user's session, under the key named by the constant string value of Action.LOCALE_KEY. Your own application logic can set this attribute at any time, or you can ask Struts to set it automatically (if not already set) based on the Accept-Language HTTP header included with the request. There are two mechanisms by which you request Struts to perform this service:



Copyright © 2000-2001 - Apache Software Foundation