blob: 09e0cee3098b0549054311df32c5983c64eb8062 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
<!--NewPage-->
<HTML>
<HEAD>
<!-- Generated by javadoc on Fri Jun 15 16:53:35 PDT 2001 -->
<TITLE>
Apache Struts API Documentation: Package org.apache.struts.util
</TITLE>
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../stylesheet.css" TITLE="Style">
</HEAD>
<BODY BGCOLOR="white">
<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_top"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
<TR>
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
<A NAME="navbar_top_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
<TR ALIGN="center" VALIGN="top">
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
</TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
</EM>
</TD>
</TR>
<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;<A HREF="../../../../org/apache/struts/upload/package-summary.html"><B>PREV PACKAGE</B></A>&nbsp;
&nbsp;NEXT PACKAGE</FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
<A HREF="../../../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
&nbsp;<A HREF="package-summary.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
</TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->
<HR>
<H2>
Package org.apache.struts.util
</H2>
The Utilities package provides a variety of families of classes,
to solve problems that are commonly encountered in building web applications.
<P>
<B>See: </B>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="#package_description"><B>Description</B></A>
<P>
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
<TD COLSPAN=2><FONT SIZE="+2">
<B>Class Summary</B></FONT></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="ArrayStack.html">ArrayStack</A></B></TD>
<TD>Implementation of the <code>java.util.Stack</code> API that is based on
an <code>ArrayList</code> rather than a <code>Vector</code>.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="BeanUtils.html">BeanUtils</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Beanutils package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="ConvertUtils.html">ConvertUtils</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Beanutils package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="ErrorMessages.html">ErrorMessages</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>Use org.apache.struts.action.ActionErrors instead</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="FastArrayList.html">FastArrayList</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Collections package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="FastHashMap.html">FastHashMap</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Collections package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="FastTreeMap.html">FastTreeMap</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Collections package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="GenericConnection.html">GenericConnection</A></B></TD>
<TD>Generic wrapper implementation of a <strong>Connection</strong> that
works with <code>GenericDataSource</code> to wrap connections for any
JDBC driver.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="GenericDataSource.html">GenericDataSource</A></B></TD>
<TD>Generic data source implementation of the <code>DataSource</code>
interface.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="IteratorAdapter.html">IteratorAdapter</A></B></TD>
<TD>Utility method for converting Enumeration to an Iterator
class.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="MessageResources.html">MessageResources</A></B></TD>
<TD>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 <code>MessageFormat</code>
class to produce internationalized messages with parametric replacement.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="MessageResourcesFactory.html">MessageResourcesFactory</A></B></TD>
<TD>Factory for <code>MessageResources</code> instances.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="PropertyMessageResources.html">PropertyMessageResources</A></B></TD>
<TD>Concrete subclass of <code>MessageResources</code> that reads message keys
and corresponding strings from named property resources in the same manner
that <code>java.util.PropertyResourceBundle</code> does.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="PropertyMessageResourcesFactory.html">PropertyMessageResourcesFactory</A></B></TD>
<TD>Factory for <code>PropertyMessageResources</code> instances.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="PropertyUtils.html">PropertyUtils</A></B></TD>
<TD><B>Deprecated.</B>&nbsp;<I>At some point after Struts 1.0 final, will be replaced by
an equivalent class in the Jakarta Commons Beanutils package.</I></TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="RequestUtils.html">RequestUtils</A></B></TD>
<TD>General purpose utility methods related to processing a servlet request
in the Struts controller framework.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="ResponseUtils.html">ResponseUtils</A></B></TD>
<TD>General purpose utility methods related to generating a servlet response
in the Struts controller framework.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD WIDTH="15%"><B><A HREF="ServletContextWriter.html">ServletContextWriter</A></B></TD>
<TD>A PrintWriter implementation that uses the logging facilities of a
<code>javax.servlet.ServletContext</code> to output its results.</TD>
</TR>
</TABLE>
&nbsp;
<P>
<A NAME="package_description"><!-- --></A><H2>
Package org.apache.struts.util Description
</H2>
<P>
The Utilities package provides a variety of families of classes,
to solve problems that are commonly encountered in building web applications.
<br><br>
<a name="doc.Description"></a>
<div align="center">
<a href="#doc.Intro">[Introduction]</a>
<a href="#doc.Beans">[Beans and Properties]</a>
<a href="#doc.Collections">[Collection Classes]</a>
<a href="#doc.JDBC">[JDBC Connection Pool]</a>
<a href="#doc.Messages">[Message Resources]</a>
</div>
<hr>
<a name="doc.Intro"></a>
<h3>Introduction</h3>
<p>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:</p>
<ul>
<li><a href="#doc.Beans">Beans and Properties</a> - A family of utility
classes for manipulating JavaBeans, as well as getting and setting
properties, without hard coding the names or data types of the
property getter and setter methods.</li>
<li><a href="#doc.Collections">Collection Classes</a> - A family of specialized
classes supporting the Collections API, designed for use in multithread
environments where the vast majority of accesses are read only.</li>
<li><a href="#doc.JDBC">JDBC Connection Pool</a> - A very simple connection
pool that can be utilized in web applications or other environments that
need to share a limited number of JDBC Connections across a much larger
number of active users.</li>
<li><a href="#doc.Messages">Message Resources</a> - A family of classes that
features access to internationalized message strings based on a message
key coupled with a <code>java.util.Locale</code> object representing a
particular user's preferred language.</li>
</ul>
<hr>
<a name="doc.Beans"></a>
<h3>Beans and Properties</h3>
<p>FIXME</p> <p>FIXME some parts of this might me moved to Taglibs</p>
<p> The <code>BeanUtils</code> and <code>PropertyUtils</code> utilities are
used through out struts including the <code>IteratorTag, WriteTag</code>.
Much of these utilities rely on and make use of Java reflection, to manipulate
<a href='http://developer.java.sun.com/developer/onlineTraining/Beans/beans02/'>
Java beans </a>. Creating a <b>valid</b> Java bean is essential !
Briefly referring to the example class <code>ProductBean</code>
below would follow these rules :
<ul>
<li> The class <b>must</b> a null constructor, or no constructor </li>
<li> It's class declaration <b>must</b> be public </li>
<li> The name for the property say 'value' would have a 'get' method of getValue()</li>
<li> The 'get' and 'set' methods to be visible <b>must</b> be public.</li>
<li> If desired the 'is' prefix can be used in place if 'get' for a boolean.</li>
<li> Other requirements can be found
<a href='http://developer.java.sun.com/developer/onlineTraining/Beans/beans02/'>
here</a>.
</ul>
<pre>
public class ProductBean() {
private String value;
public String getvalue() (return this.value}
public void setvalue(String value) (this.value = value}
}
</pre>
</p>
<p> Observing these conventions will avoid unnecessary errors and save time.</p>
<p>
This makes it possible to create a JSP page such as:
<pre>
&lt;logic:iterate id="product" name="receivedForm" property="receivedList"&gt;
&lt;bean:write name="product" property="description" /&gt;
&lt;bean:write name="product" property="value" /&gt;
&lt;/logic:iterate&gt;
</pre>
In this case receiveForm is an ActionForm, with a definition such as
<pre>
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
</pre>
<hr>
<a name="doc.Collections"></a>
<h3>Collection Classes</h3>
<h5>Background</h5>
<p>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 <code>java.util.Collection</code>,
<code>java.util.List</code>, <code>java.util.Map</code>, and
<code>java.util.Set</code>. Compared to the collection classes available in
JDK 1.1 (principally <code>java.util.Hashtable</code> and
<code>java.util.Vector</code>), the new classes offer much richer functionality
as well as the opportunity to improve performance.</p>
<p>The performance increase potential comes from the fact that none of the
methods used to access the new collection classes are <code>synchronized</code>
as were the methods of <code>Hashtable</code> and <code>Vector</code>. 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.
</p>
<p>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 <code>ActionMapping</code> instances (each corresponding to an
<code>&lt;action&gt;</code> element in the <code>struts-config.xml</code>
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.</p>
<p>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.</p>
<h5>Theory of Operation</h5>
<p>Each of the available collection classes operates in one of two modes:
<em>fast</em> or <em>slow</em>. When first created, the collection operates
in <em>slow</em> mode, which is appropriate for initially populating the
contents of the collection. Once the initial population is complete, switch
to <em>fast</em> mode by calling <code>setFast(true)</code> for maximum
performance when most accesses are read-only.</p>
<p>When operating in <em>slow</em> 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 <code>Hashtable</code> and
<code>Vector</code> 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.</p>
<p>Using <em>fast</em> mode, on the other hand, causes method calls to operate
in the following manner:</p>
<ul>
<li>Method calls that access information from the collection, but do not
modify it, are executed <strong>without</strong> synchronization.</li>
<li>Method calls that modify the structure of a collection do so by
synchronizing, cloning the existing collection instance, modifying the
cloned instance, and then replacing the current collection instance.</li>
</ul>
<p>As you can see, modification operations are <strong>much</strong> more
expensive when operating in <em>fast</em> mode, but doing things in this way
allows read only operations, which should be the vast majority, to operate at
maximum speed.</p>
<p>If your collection will <strong>never</strong> be accessed in a multithread
environment, you should use one of the standard collection classes instead,
without synchronization, for maximum performance.</p>
<h5>Available Collection Classes</h5>
<p>The following collection classes, with the ability to operate in either
<em>fast</em> or <em>slow</em> mode, are included:</p>
<ul>
<li><a href="FastArrayList.html">org.apache.struts.util.FastArrayList</a> -
Similar in functionality to <code>java.util.ArrayList</code>.</li>
<li><a href="FastHashMap.html">org.apache.struts.util.FastHashMap</a> -
Similar in functionality to <code>java.util.HashMap</code>.</li>
<li><a href="FastTreeMap.html">org.apache.struts.util.FastTreeMap</a> -
Similar in functionality to <code>java.util.TreeMap</code>.</li>
</ul>
<a name="doc.JDBC"></a>
<h3>JDBC Connection Pool</h3>
<h5>Background</h5>
<p>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.</p>
<p>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.</p>
<p>To deal with this situation, several basic strategies are possible:</p>
<ol>
<li>Open a connection on each request, do whatever processing is required,
and then close the connection.</li>
<li>Open a connection for each user, and store it in the user's session.</li>
<li>Share a "pool" of open connections between all of the application's
current users.</li>
</ol>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Struts provides a simple connection pool class called
<code>org.apache.struts.util.GenericDataSource</code>. 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 <code>GenericDataSource</code> class implements the
<code>javax.sql.DataSource</code> 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.</p>
<p>For more information about the JDBC 2.0 Standard Extension API, you can
download the spec (and the corresponding API classes), from
<a href="http://java.sun.com/products/jdbc">http://java.sun.com/products/jdbc</a>. 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.</p>
<h5>Initializing and Finalizing the Connection Pool</h5>
<p>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).</p>
<p>To configure a <code>GenericDataSource</code> instance, you must first
create one:</p>
<pre>
GenericDataSource dataSource =
new GenericDataSource();
</pre>
<p>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 <a href="GenericDataSource.html">GenericDataSource</a> class for
more details on the available properties). An example of configuring the
connection pool object to a Postgres database might look like this:</p>
<pre>
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");
</pre>
<p>Finally, you must <code>open()</code> the connection pool. This will
establish the initial connections to the database (based on the value you have
configured for the <code>minCount</code> property). As you use connections
from the pool in multiple threads, additional connections (up to the number
you specify with the <code>maxCount</code> property) will be created as needed.
</p>
<pre>
try {
dataSource.open();
} catch (SQLException e) {
... deal with exception ...
}
</pre>
<p>When you are completely through with the connection pool, you can gracefully
close all of the currently open database connections by executing</p>
<pre>
try {
dataSource.close();
} catch (SQLException e) {
... deal with exception ...
}
</pre>
<h5>Using the Generic Connection Pool</h5>
<p>To access the database from within an application class, you must follow a
simple four-step procedure each time you need a connection:</p>
<ol>
<li>Acquire a connection from the connection pool.</li>
<li>Perform the database operations required by your application.</li>
<li>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).</li>
<li>"Close" the connection, which returns it to the connection pool for
reuse later.</li>
</ol>
<p>An example code sequence that performs this procedure might look like
this:</p>
<pre>
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;
}
}
</pre>
<p>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 <code>getConnection()</code>
is a customized "wrapper" around a real JDBC Connection instance. Calling
<code>close()</code> on this wrapper simply causes this connection to be
returned to the pool.</p>
<p>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.</p>
<p>To avoid this problem, your application logic must ensure that it
<strong>ALWAYS</strong> 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 <code>finally</code> 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.</p>
<h5>Using Connection Pools with the Struts Controller Servlet</h5>
<p>If your application is running underneath the Struts controller servlet
(<code>org.apache.struts.action.ActionServlet</code>), you can take advantage
of the servlet's ability to preconfigure one or more connection pools for you,
based on information included in the <code>struts-config.xml</code> file.
Simply include a section that looks like this:</p>
<pre>
&lt;data-sources&gt;
&lt;data-source&gt;
&lt;set-property property="autoCommit"
value="false"/&gt;
&lt;set-property property="description"
value="Example Data Source Configuration"/&gt;
&lt;set-property property="driverClass"
value="org.postgresql.Driver"/&gt;
&lt;set-property property="maxCount"
value="4"/&gt;
&lt;set-property property="minCount"
value="2"/&gt;
&lt;set-property property="password"
value="mypassword"/&gt;
&lt;set-property property="url"
value="jdbc:postgresql://localhost/mydatabase"/&gt;
&lt;set-property property="user"
value="myusername"/&gt;
&lt;/data-source&gt;
&lt;/data-sources&gt;
</pre>
<p>After being initialized, the connection pools will be stored as servlet
context attributes under the bean name specified by the <code>key</code>
attribute. If you did not specify a <code>key</code>, the default key is the
value of the string constant <code>Action.DATA_SOURCE_KEY</code>. Thus, you
can access and utilize a connection, from within an <code>Action</code> class,
like this (for the default data source):</p>
<pre>
DataSource dataSource = (DataSource)
servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);
conn = dataSource.getConnection();
... perform required functions as in the previous example ...
conn.close();
</pre>
<hr>
<a name="doc.Messages"></a>
<h3>Message Resources</h3>
<h5>Background</h5>
<p>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.</p>
<p>The standard Java platform includes a family of classes
(<code>java.util.ResourceBundle</code>) 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.</p>
<p>Struts includes a family of classes
(<code>org.apache.struts.util.MessageResources</code>) 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.</p>
<p>In addition to supporting dynamic selection of a Locale for message lookup,
the <code>MessageResources</code> 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
<code>java.text.MessageFormat</code> class, which supports many extended
formatting capabilities as well.</p>
<p>For more information about internationalized messages, consult the following
resources in your Java Development Kit documentation bundle:</p>
<ul>
<li><em>Internationalization Info</em> - General information on Java's standard
support for internationalized applications can be found at
<code>&lt;$JAVA_HOME/docs/guide/internat/index.html&gt;</code>.
The "Internationalization Overview" section includes useful information
about Locales, localized resources, message formatting, and other
relevant topics.</li>
<li><em>Internationalization Tutorial</em> - The Java Language Tutorial has a
comprehensive trail covering internationalization, available at:
<a href="http://java.sun.com/docs/books/tutorial/i18n/index.html">
http://java.sun.com/docs/books/tutorial/i18n/index.html</a>.</li>
<li><em>Javadoc APIs</em> - You will want to consult the Javadoc API
documentation for the following standard Java classes:
<ul>
<li><code>java.text.MessageFormat</code>
<li><code>java.util.ResourceBundle</code>
<li><code>java.util.PropertyResourceBundle</code>
<li><code>java.util.Properties</code> - See the documentation for the
<code>load()</code> method for the valid syntax of properties files
that you prepare.</li>
</ul></li>
</ul>
<h5>Using the Standard MessageResources Implementation</h5>
<p>The standard <code>MessageResources</code> implementation provided by the
Struts library uses Java properties files to initialize message strings, in a
manner very similar to that supported by the
<code>java.util.PropertyResourceBundle</code> class. The following steps are
required to use these facilities in your Java application.</p>
<p>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.</p>
<p>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 <code>Messages_fr.properties</code> and contain the following:</p>
<pre>
hi=Bonjour
</pre>
<p>while the Spanish and English files would be named
<code>Messages_es.properties</code> and <code>Messages_en.properties</code>
respectively. The corresponding message string definitions would say
<code>hi=Hola</code> and <code>hi=Hello</code> in these files.</p>
<p>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).
<p>Third, initialize a <code>MessageResources</code> 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:</p>
<pre>
public static MessageResources messages =
MessageResources.getMessageResources("com.mycompany.mypackage.Messages");
</pre>
<p>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
<code>MessageResources</code> 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.</p>
<p>To access a message string with a particular Locale, execute a statement
like this:</p>
<pre>
Locale locale = ... select the locale to be used ...
String message = messages.getMessage(locale, "hi");
</pre>
<p>In this case, the variable <code>message</code> will contain the message
string corresponding to the key "hi", in the language that corresponds to the
locale that was selected.</p>
<p>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):</p>
<pre>
hi=Hello {0}
</pre>
<p>Now, you can personalize the retrieved message like this:</p>
<pre>
Locale locale = ... select the locale to be used ...
String name = "Joe";
String message = messages.getMessage(locale, "hi", name);
</pre>
<p>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
<code>java.text.MessageFormat</code> class for more advanced uses of the
parameter replacement mechanism.</p>
<h5>Developing Your Own MessageResources Implementation</h5>
<p>In the above example, we were using the default
<code>MessageResources</code> 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:</p>
<ul>
<li>Create a customized subclass of
<code>org.apache.struts.util.MessageResources</code> that implements
message lookup operations as you require.</li>
<li>Create a customized subclass of
<code>org.apache.struts.util.MessageResourcesFactory</code> that will
create an instance of your custom <code>MessageResources</code> class
when the <code>createResources</code> method is called. Note that the
"config" argument to this method can be used to select families of
messages in any manner appropriate to your needs - you are not required
to emulate the "fully qualified Java class name" approach that is used
by the standard <code>PropertyMessageResourcesFactory</code> class.</li>
<li>Tell the <code>MessageResourcesFactory</code> class the name of the
customized <code>MessageResourcesFactory</code> implementation to use
when creating new factory instances.</li>
<li>Create a new factory instance.</li>
<li>Ask the new factory instance to create a <code>MessageResources</code>
instance for you.</li>
</ul>
<p>A code example that illustrates this technique is:</p>
<pre>
MessageResourcesFactory.setFactoryClass("com.mycompany.mypkg.MyFactory");
MessageResourcesFactory factory = MessageResourcesFactory.createFactory();
MessageResources resources =
factory.createResources("configuration information");
</pre>
<p>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.</p>
<h5>Using MessageResources With Struts</h5>
<p>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:
</p>
<ul>
<li><strong>application</strong> - The configuration string that will be
passed to the <code>createResources()</code> method of the message
resources factory, in order to identify the family of resources to be
supported. If you use the standard message resources factory, this must
be the base fully qualified name of the property resources files used
to contain these messages, as illustrated above.</li>
<li><strong>factory</strong> - Fully qualified Java class name of the
<code>MessageResourcesFactory</code> to be used. By default, the standard
implementation provided by Struts
(<code>org.apache.struts.util.PropertyMessageResourcesFactory</code>)
will be used.</li>
</ul>
<p>Struts provides several JSP custom tags that assume the existence of a
<code>java.util.Locale</code> attribute in the user's session, under the key
named by the constant string value of <code>Action.LOCALE_KEY</code>. 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
<code>Accept-Language</code> HTTP header included with the request. There are
two mechanisms by which you request Struts to perform this service:</p>
<ul>
<li>To have this service performed on every request submitted to the controller
servlet, set the servlet initialization parameter <code>locale</code> to
the value <code>true</code> in the application deployment descriptor.</li>
<li>To have this service performed by a JSP page when it is accessed directly
by a user, utilize a <code>&lt;form:html ... locale="true" ... /&gt;</code>
tag at the top of each page.</li>
</ul>
<P>
<HR>
<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_bottom"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
<TR>
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
<A NAME="navbar_bottom_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
<TR ALIGN="center" VALIGN="top">
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
</TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
</EM>
</TD>
</TR>
<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;<A HREF="../../../../org/apache/struts/upload/package-summary.html"><B>PREV PACKAGE</B></A>&nbsp;
&nbsp;NEXT PACKAGE</FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
<A HREF="../../../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
&nbsp;<A HREF="package-summary.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
</TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->
<HR>
Copyright © 2000-2001 - Apache Software Foundation
</BODY>
</HTML>