Haven't quite decided where to use this, and it didn't seem like the
best time to squeeze something new into the docs =:0), so I thought I'd
post it here for now, in case it were of interest to some.
WHITHER ACTION MAPPINGS?
We write applications to do things for people. We might say, for
example, that we want the appication to create a mail-merge job for us.
Some developers call these top-level tasks "client stories". In
practice, to do a big job like this, an application will need to take
several smaller steps. We'll need to obtain the information from the
user about which mail-merge job to create. We'll need to find the items
to merge. We'll need to put the items together with a template, and
we'll need to present the result back to the user. Some developers call
these smaller tasks "use cases". To complete a client story, we usually
chain several use cases together. A chain of use cases is sometimes
called a workflow.
Before doing any thing for us, most applications wait to be asked. When
we ask the application to do something, we usually need to provide a
variety of details. If we ask the application to store a name and
address, we need to provide the name and address to go along with the
request.
HTML Forms
A web application collects such details through a HTML form. Under the
hood, a HTML form submits a request to something called an "action". The
action is a identifer that the web server can use to route the request
to whatever software is suppose to handle it. The HTML specification
does not much care what software is used to handle the request. It
simply gives us a place where we can invoke the software we want to use.
Action Handlers
The simplest handler for an action is another HTML page. This doesn't
accomplish much by itself, since a standard HTML page is static. Another
simple way to handle an action is to install scripting software into
your web server. This includes programs like Perl and Python. The server
gives the request to the scripting software, and the scripting softare
returns a response. The server sends the response back to the web
browser (or other client).
Usually, the response will be in the form of another HTML page. Here, we
might have a form action like action="/scripts/merge-form.pl". The HTML
page returned by such a script may not exist as a separate file. The
script can generate it "on the fly".
Server Pages
A more sophisticated way to handle an action is with a server-page. The
software for handling the server-page is also installed into the web
server. When a request for a certain type of page, say one matching the
extension .jsp, comes along, the server passes the request to the
server-page handler. The handler calls upon the page much like a script.
The request acts as input to the server-page, and the page renders a
response, just as scripting software would. Here, we might have a format
action like action="/pages/merge-form.jsp".
Servlets
Java web applications can also use servlets. A servlet is a binary Java
class. After installing the servlet handler (or "container"), you can
register the servlet to handle requests that match a certain pattern.
These might look like server pages (*.do), or like a sub-directory
(/do/*). As with the other methods, the web server hands the request to
the servlet, and the servlet hands back a response. (The web
specification requires a response for every request.)
Most elements in a servlet class are there to support getting a request
and returning a response. When Java developers write servlets, they will
usually subclass a working servlet and add one relatively small method
for doing some certain thing. Usually this certain thing corresponds to
handling the input from a particular HTLM form. When this is true, a
developer could register the servlet under a concrete identifier, rather
than a pattern. This servlet would then handle one specific request (or
"action").
Some servlets, like the Struts ActionServlet, let you put this
specialized method into another Java class alogether. The ActionServlet
is registed to handle all the requests matching a pattern. Each specific
request (or "action") can be assigned to a Java class. Since these
classes are most often called when a HTML form is submitted, Struts
calls these "Action" classes.
ActionMappings
Struts keeps the list of action identifiers (or "paths") and their
corresponding Action classes in a collection called the ActionMappings.
Each entry in the collection is an ActionMapping object. You could
create the ActionMappings collection using a Java class, but that's a
lot of work. Struts can load the ActionMappings at startup time by
reading a configuration file written in XML. (The servlet container uses
a similar file to load the Java servlet classes.)
FormBeans
HTML forms often include several bits of information. A form that is
adding a record to a database might include a dozen fields or more. The
Java servlet container turns the request into a Java object which it
passes along to the appropriate servlet. Struts in turn passes the
request object to the Action class. You can look inside this object and
get the names of every field submitted with the request and then also
ask for the corresponding value. But this too is a lot of work.
Most Java application now use JavaBeans to represent fields like a name
and address. A reasonable thing for a web developer to do is create a
JavaBean with properties that match the attributes they expect a form to
submit. If you create a JavaBean to match the HTML form, Struts can
populate it for you automatically. Since this is the form that you
submit with an action, Struts calls them ActionForms.
Validation
In practice, many HTML forms reuse the same set of fields. A developer
can often create a single ActionForm that can be used with several
different actions. To make the ActionForm's easier to reuse, Struts
provides a FormBean class in the configuration file.
Web developers have to be very careful about the information that is
passed to their application. It is very easy to for people to create a
request that looks like it came from your form. But it could contain any
sort of data whatsoever. The data may not be what your application
expects. It is very important that web developers validate input before
letting it into an application.
Accordingly, the Struts ActionForm includes a validate method.
Developers can use this to test the input. If the input cannot be used,
the method can return a list of messages. Struts then forwards the
request, including the ActionForm object, back to an input page. The
Struts tags can redisplay the data from the ActionForm, along with the
messages, so the user can correct the errors and try again.
FormBean Names
The input page may contain more than one form. This means that Struts
can't save the ActionForm under a constant name. To avoid collissions,
each form (or action) should be able to have a name of its own. To help
you manage an ActionForm's logical name, Struts provides a form-bean
class in the configuration file. Each form-bean has a unique name and a
property to indicate the ActionForm type. If two forms will appear on
the same page, but can share the same ActionForm class, you can create
two form-beans with different names but the same ActionForm type.
The (optional) Struts Validator uses the ActionForm attribute name to
identify which validation to use with a request. When validate is
called, the ActionServlet passes along the ActionMapping as part of the
signature. The validator looks up its own form for that attribute and
applies the appropriate validators.
Action Stories
In practice, the ActionMapping attribute, or form-bean name, is
identifying the use-case underlying the Struts action. The form-bean
exposes the set of fields the use-case needs. The validator-form
confirms that all the fields are "present and accounted for". The Action
class associated with the same attribute provides the link between the
web presentation layer and your application's business logic.
If you are designing your application first, and then attaching it to
Struts, a sound approach is to use the ActionMapping attribute to link
your use case with the Struts ActionMapping and the corresonding HTML form.
To provide the best flexibility, the HTML form's action attribute is not
directly linked to the ActionMapping's path property. It is tempting to
consider using the same token for the ActionMapping attribute and path.
But the path is used as an URI, which may have "business requirements"
of its own. The URI paths might have to follow a certain pattern to
fulfill security requirements. Since you do not want web requirements to
trickle up to the business tier, it's best to use different tokens. You
might start out with the pair being quite similar (like "/permit/search"
for the path and "permit_search" for the name), but eventually you might
need to change one but not the other.
Conclusion
When designing the presentation layer, consider form-beans and
their attributes as an embodiment of your application's use-cases or
stories. Rather than use these as "throw-away" names, link them into
your overall architechture. This helps you visualize how an request
progresses from the browser, through your controller, up to your module,
and back again.
-Ted.
--
Ted Husted,
Struts in Action <http://husted.com/struts/book.html>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]