This section focuses on the task of building the View components for use with Struts. Many applications rely on JavaServer Pages (JSP) technology to create the presentation layer. The distribution includes a comprehensive JSP tag library that provides support for building internationalized applications, as well as for interacting with input forms. Several other topics related to the View components are briefly discussed.
A few years ago, application developers could count on having to support only residents of their own country, who are used to only one (or sometimes two) languages, and one way to represent numeric quantities like dates, numbers, and monetary values. However, the explosion of application development based on web technologies, as well as the deployment of such applications on the Internet and other broadly accessible networks, have rendered national boundaries invisible in many cases. This has translated (if you will pardon the pun) into a need for applications to support internationalization (often called "i18n" because 18 is the number of letters in between the "i" and the "n") and localization .
The framework builds upon the standard classes available on the Java platform to build internationalized and localized applications. The key concepts to become familiar with are:
Locale
.
Each
Locale
represents a particular choice of country and
language (plus an optional language variant), and also
a set of
formatting assumptions for things like numbers and
dates.
java.util.ResourceBundle
class provides the fundamental tools for supporting
messages in
multiple languages.
See the Javadocs for the
ResourceBundle
class, and the
information on Internationalization in the
documentation bundle for your
JDK release, for more information.
ResourceBundle
allows you to define
resources using the same "name=value" syntax used to
initialize
properties files.
This is very convenient for preparing resource bundles
with messages
that are used in a web application, because these
messages are
generally text oriented.
java.text.MessageFormat
class allows you to replace portions of a message
string (in this
case, one retrieved from a resource bundle) with
arguments specified
at run time.
This is useful in cases where you are creating a
sentence, but the
words would appear in a different order in different
languages.
The placeholder string
{0}
in the message is replaced by
the first runtime argument,
{1}
is replaced by the
second argument, and so on.
org.apache.struts.util.MessageResources
lets you treat
a set of resource bundles like a database, and allows
you to request
a particular message string for a particular Locale
(normally one
associated with the current user) instead of for the
default Locale
the server itself is running in.
com.mycompany.mypackage
, so it is stored in a directory
(relative to your source directory) named
com/mycompany/mypackage
.
To create a resource bundle called
com.mycompany.mypackage.MyApplication
, you would create the
following files in the
com/mycompany/mypackage
directory:
prompt.hello=Hello
prompt.hello=Bonjour
You can have resource bundle files for as many
languages as you need.
com.mycompany.mypackage.MyApplication
.
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>
com.mycompany.mypackage.MyResources
</param-value>
</init-param>
<!-- ... -->
</servlet>
MyResources.properties
file in your application's
classes
folder.
You can then simply specify "myResources" as the
application value.
Just be careful it is not deleted if your build script
deletes
classes as part of a "clean" target.
If it does, here is an Ant task to run when compiling your
application
that copies the contents of a
src/conf
directory to the
classes
directory:
<!-- Copy any configuration files --> <copy todir="classes"> <fileset dir="src/conf"/> </copy>
At one time or another, most web developers have built
forms using
the standard capabilities of HTML, such as the
<input>
tag.
Users have come to expect interactive applications to have
certain
behaviors, and one of these expectations relates to error
handling -- if
the user makes an error, the application should allow them
to fix just
what needs to be changed -- without having to re-enter any
of the rest
of the information on the current page or form.
Fulfilling this expectation is tedious and cumbersome when
coding with
standard HTML and JSP pages.
For example, an input element for a
username
field might
look like this (in JSP):
<input type="text" name="username" value="<%= loginBean.getUsername() >"/>
which is difficult to type correctly, confuses HTML developers who are not knowledgeable about programming concepts, and can cause problems with HTML editors. Instead, Struts provides a comprehensive facility for building forms, based on the Custom Tag Library facility of JSP 1.1. The case above would be rendered like this using Struts:
<html:text property="username"/>;
with no need to explicitly refer to the JavaBean from which the initial value is retrieved. That is handled automatically by the JSP tag, using facilities provided by the framework.
HTML forms are sometimes used to upload other files. Most browsers support this through a <input type="file"> element, that generates a file browse button, but it's up to the developer to handle the incoming files. Struts handles these "multipart" forms in a way identical to building normal forms.
For an example of using Struts to create a simple login form, see the Buiding an ActionForm Howto.
Property references in JSP pages using the Struts framework can reference Java Bean properties as described in the JavaBeans specification. Most of these references refer to "scalar" bean properties, referring to primitive or single Object properties. However, Struts, along with the Commons Beanutils library, allow you to use property references which refer to individual items in an array, collection, or map, which are represented by bean methods using well-defined naming and signature schemes.
Documentation on the Beanutils package can be found at http://commons.apache.org/beanutils/api/index.html. More information about using indexed and mapped properties in Struts can be found in the FAQ describing Indexed Properties, Mapped Properties, and Indexed Tags.
Struts defines HTML tags for all of the following types of input fields, with hyperlinks to the corresponding reference information.
form
tag, so that
the field knows what bean to use for initializing
displayed values.
validate(ActionMapping mapping, HttpServletRequest request);
validate
method is called by the controller servlet after
the bean properties have been populated, but before the
corresponding
action class's
execute
method is invoked.
The
validate
method has the following options:
null
or a zero-length ActionErrors instance,
and the controller servlet will proceed to call the
perform
method of the appropriate
Action
class.
ActionMessage
's, which
are classes that contain the error message keys (into
the
application's
MessageResources
bundle) that should be
displayed.
The controller servlet will store this array as a
request attribute
suitable for use by the
<html:errors>
tag, and
will forward control back to the input form
(identified by the
input
property for this
ActionMapping
).
validate
method returns
null
, and the controller servlet will assume that any
required validation is done by the action class.
One common approach is to perform simple, prima facia
validations using
the ActionForm
validate
method, and then handle the
"business logic" validation from the Action.
The Struts Validator, covered in the next section, may be
used to easily
validate ActionForms.
src/example
directory,
in package
org.apache.struts.example
, along with the other Java
classes that are used in this application.
<%@ include file="xxxxx" %>
directive can
include a file that contains Java code or JSP tags.
The code in the included file can even reference
variables declared
earlier in the outer jsp page.
The code is inlined into the other JavaServer Page
before it is
compiled so it can definitely contain more than just
HTML.
<jsp:include page="xxxxx"
flush="true" />
) is processed at request time, and is
handled transparently by the server.
Among other things, that means you can conditionally
perform the
include by nesting it within a tag like
equal
by using it's
parameter attribute.
<html> <body> <tiles:insert attribute="body"/> </body> </html>
<h1>This is my homepage</h1>
<tiles-definitions>
<definition
name="layout"
path="/layout/layout.jsp">
<put name="body" value=""/>
</definition>
<definition name="homepage" extends="layout">
<put
name="body"
value="/index.jsp"/>
</definition>
<tiles-definitions>
<plug-in
className="org.apache.struts.tiles.TilesPlugin">
<set-property
property="definitions-config"
value="/WEB-INF/tiles-defs.xml"/>
</plug-in>
<action path="/index" type="org.apache.struts.actions.ForwardAction" parameter="homepage"/>