You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by hu...@apache.org on 2006/01/21 01:21:00 UTC
svn commit: r370938 [27/50] - in /struts: action/trunk/
action/trunk/conf/java/ action/trunk/src/java/org/apache/struts/
action/trunk/src/java/org/apache/struts/action/
action/trunk/src/java/org/apache/struts/chain/
action/trunk/src/java/org/apache/str...
Modified: struts/action/trunk/xdocs/faqs/newbie.xml
URL: http://svn.apache.org/viewcvs/struts/action/trunk/xdocs/faqs/newbie.xml?rev=370938&r1=370937&r2=370938&view=diff
==============================================================================
--- struts/action/trunk/xdocs/faqs/newbie.xml (original)
+++ struts/action/trunk/xdocs/faqs/newbie.xml Fri Jan 20 16:19:02 2006
@@ -18,819 +18,1213 @@
-->
<document>
-<properties>
-<title>Newbie FAQ</title>
-</properties>
-<body>
-<section href="faq" name="Newbie FAQ">
-
-<a name="contents"/>
-<subsection name="Index">
-
- <p>
- Here are answers to the most common questions people ask when using
- the framework on their first project.
- </p>
-
- <ul>
-
- <li>
- <a href="#modules">What is a modular application? What does
- module-relative mean?</a>
- </li>
-
- <li>
- <a href="#naming">Why are some of the class and element names
- counter-intuitive?</a>
- </li>
-
- <li>
- <a href="#actionForms">Whither ActionForms?</a>
- </li>
-
- <li>
- <a href="#actionFormInterface">Why is ActionForm a base class rather than an interface?</a>
- </li>
-
- <li>
- <a href="#news">Can I use other beans or hashmaps with ActionForms?</a>
- </li>
-
- <li>
- <a href="#authenticate">How can I authenticate my users?</a>
- </li>
-
- <li><a href="#jsp">Do I have to use JSPs with my application?</a></li>
-
- <li>
- <a href="#formbeans">Do ActionForms have to be true JavaBeans?</a>
- </li>
-
- <li>
- <a href="#separate">Do I have to have a separate ActionForm bean
- for every HTML form?</a>
- </li>
-
- <li>
- <a href="#prepopulate">How can I prepopulate a form?</a>
- </li>
-
- <li>
- <a href="#noForm">Can I have an Action without a form?</a>
- </li>
-
- <li>
- <a href="#requiredif">Can you give me a simple example of using the requiredif Validator rule?</a>
- </li>
-
- <li>
- <a href="#validate">When is the best time to validate input?</a>
- </li>
-
- <li>
- <a href="#avoidValidate">How can I avoid validating a form before data is entered?</a>
- </li>
-
- <li>
- <a href="#wizard">How can I create a "wizard" workflow?</a>
- </li>
-
- <li>
- <a href="#chaining">How can I "chain" Actions?</a>
- </li>
-
- </ul>
-
- <p>
- If you like to <a href="helping.html">contribute</a>,
- there is a list of <a href="#undocumented"> undocumented questions</a>
- at the end of this page.
- </p>
-
-</subsection>
-
-
-<a name="modules"/>
-<subsection name="What is a modular application? What does module-relative mean?">
-
-<p>
-Since Struts 1.1, the framework supports multiple application modules. All applications have at
-least one root, or default, module. Like the root directory in a file system, the default application
-has no name. (Or is named with an empty string, depending your viewpoint.) Developing an application
-with only a default module is no different from how applications were developed under Struts 1.0.
-Since Struts 1.1, you can add additional modules to your application, each of which can have their
-own configuration files, messages resources, and so forth. Each module is developed in the same way as
-the default module. Applications that were developed as a single module can added to a multiple
-module application, and modules can promoted to a standalone application without change. For more
-about configuring your application to support multiple modules, see
-<a href="../userGuide/configuration.html#dd_config_modules">Configuring Applications</a> in the
-User Guide.
-</p>
-
-<p>
-But to answer the question =:0), a modular application is an application that uses more than
-one module. Module-relative means that the URI starts at the module level, rather than at
-the context level, or the absolute-URL level.
-</p>
-<ul>
-<li>Absolute URL: http://localhost/myApplication/myModule/myAction.do</li>
-<li>context-relative: /myModule/myAction.do</li>
-<li>module-relative: /myAction.do</li>
-</ul>
-
-<p>
-The Struts Examples application is a modular application that was assembled from several
-applications that were created independently.
-</p>
-
-</subsection>
-
-<a name="naming"/>
-<subsection name="Why are some of the class and element names counter-intuitive?">
-<p>
-The framework grew in the telling and, as it evolved, some of the names
-drifted.
-</p>
-<p>The good thing about a nightly build, is that everything becomes
-available to the community as soon as it is written. The bad thing about
-a nightly build is that things like class names get locked down early and
-then become difficult to change.
-</p>
-</subsection>
-
-<a name="actionForms"/>
-<subsection name="Whither ActionForms?">
-<p>
-<a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19281.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19281.html</a><br/>
-<a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html</a><br/>
-<a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg20833.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg20833.html</a><br/>
-</p>
-</subsection>
-
-<a name="actionFormInterface"/>
-<subsection name="Why is ActionForm a base class rather than an interface?">
-<p>
-Originally, the rationale as that making ActionForm a class takes advantage of the single
-inheritance restriction of Java to it makes it more difficult for people to do
-things that they should not do. At the time, EJBs were becoming popular, and
-most developers were trying to combine EJB remoting with ActionForms,
-and the result was not pretty.
-</p>
-<p>
-Since then, most developers use different approaches to data persistent,
-and most developers now have a good understanding of why we want to separate
-the model from the view.
-Accordingly, we do plan to introduce more interfaces into the framework.
-It's just a matter of when.
-</p>
-<p>
-Meanwhile, DynaActionForms relieve developers of maintaining simple ActionForms.
-For near zero maintenance, try
-<a href="http://www.niallp.pwp.blueyonder.co.uk/">LazyActionForm</a>
-and Hubert Rabago's <a href="https://formdef.dev.java.net/">FormDef</a>.
-</p>
-</subsection>
-
-<a name="JavaBeans"/>
-<subsection name="Do ActionForms have to be true JavaBeans?">
-<p>
-The utilities that the framework uses (Commons-BeanUtils since 1.1) require that ActionForm properties follow
-the JavaBean patterns for mutators and accessors (get*,set*,is*). Since the framework uses the Introspection API
-with the ActionForms, some containers may require that all the JavaBean patterns be followed, including
-declaring "<code>implements Serializable</code>" for each subclass. The safest thing is to review the
-<a href="../userGuide/preface.html#javabeans">JavaBean specification</a> and follow all the prescribed patterns.
-</p>
-<p>
-Since Struts 1.1, you can also use DynaActionForms and mapped-backed forms, which are not true JavaBeans.
-For more see <a href="../userGuide/building_controller.html#action_form_classes">ActionForm classes</a> in the User Guide
-and <a href="#otherBeans">Using Hashmaps with ActionForms</a> in this FAQ.
-</p>
-</subsection>
-
-<a name="otherBeans"/>
-<subsection name="Can I use other beans or hashmaps with ActionForms?">
- <p>
- Yes. There are several ways that you can use other beans or hashmaps with ActionForms.
- </p>
- <ul>
- <li>
- ActionForms can have other beansor hashmaps as properties
- </li>
- <li>
- "Value Beans" or "Data Transfer Objects" (DTOs) can be used independently of
- ActionForms to transfer data to the view
- </li>
- <li>
- ActionForms can use Maps to support "dynamic" properties (since Struts 1.1)
- </li>
- </ul>
- <p>
- ActionForms (a.k.a. "form beans") are really just Java beans (with a few
- special methods) that the framework creates and puts into session or request scope for you.
- There is nothing preventing you from using other beans, or including
- them in your form beans. Here are some examples:
- </p>
- <p>
- <em>Collections as properties</em> Suppose that you need to display a pulldown list of
- available colors on an input form in your application. You can include a string-valued
- <code>colorSelected</code> property in your <code>ActionForm</code> to represent the user's
- selection and a <code>colorOptions</code> property implemented as a <code>Collection</code>
- (of strings) to store the available color choices. Assuming that you have defined the getters
- and setters for the <code>colorSelected</code> and <code>colorOptions</code> properties
- in your <code>orderEntryForm</code> form bean, you can render the
- pulldown list using:
- </p>
- <source>
- <html:select property="colorSelected">
- <html:options property="colorOptions" name="orderEntryForm"/>
- </html:select>
- </source>
- <p>
- The list will be populated using the strings in the <code>colorOptions</code>
- collection of the <code>orderEntryForm</code> and the value that the user selects
- will go into the <code>colorSelected</code> property that gets posted to the subsequent
- <code>Action</code>. Note that we are assuming here that the <code>colorOptions</code>
- property of the <code>orderEntryForm</code> has already been set.
- </p>
- <p>
- See <a href="#prepopulate">How can I prepopulate a form?</a> for instructions on how to set
- form bean properties before rendering edit forms that expect properties to be pre-set.
- </p>
- <p>
- <em>Independent DTO</em> An <code>Action</code> that retrieves a list of open orders (as an
- <code>ArrayList</code> of <code>Order</code> objects) can use a DTO independently of any
- form bean to transfer search results to the view. First, the Action's
- <code>execute</code> method performs the search and puts the DTO into the request:
- </p>
- <source>
- ArrayList results = businessObject.executeSearch(searchParameters);
- request.setAttribute("searchResults",results);
- </source>
- <p>
- Then the view can iterate through the results using the "searchResults" request key to
- reference the DTO:
-` </p>
- <source>
- <logic:iterate id="order" name="searchResults" type="com.foo.bar.Order">
- <tr><td><bean:write name="order" property="orderNumber"/><td>
- <td>..other properties...</td></tr>
- </logic:iterate>
- </source>
- <p>
- See also: <a href="../userGuide/building_controller.html#map_action_form_classes">Map-Backed ActionForms</a> (since Struts 1.1)
- </p>
-</subsection>
-
-<a name="authenticate"/>
-<subsection name="How can I authenticate my users?">
-<p>
-<a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24504.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24504.html</a><br/>
-<a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22949.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22949.html</a>
-</p>
-</subsection>
-
-<a name="jsp"/>
-<subsection name="Do I have to use JSPs with my application?">
-
- <p>
- The short answer to this question is: No, you are not limited to
- JavaServer Pages.
- </p>
-
- <p>
- The longer answer is that you can use any type of presentation technology
- which can be returned by a web server or Java container.
- The list includes but is not limited to:
- </p>
-
- <ul>
-
- <li>
- JavaServer Pages,
- </li>
-
- <li>
- HTML pages,
- </li>
-
- <li>
- WML files,
- </li>
-
- <li>
- Java servlets,
- </li>
-
- <li>
- Velocity templates, and
- </li>
-
- <li>
- XML/XLST
- </li>
-
- </ul>
-
- <p>
- Some people even mix and match apparently unrelated technologies,
- like PHP, into the same web application.
- </p>
-
-</subsection>
-
-<a name="formbeans"/>
-<subsection name="Do ActionForms have to be true JavaBeans?">
-
- <p>ActionForms are added to a servlet scope (session or request)
- as beans. What this means is that, for certain functionality to
- be available, your ActionForms will have to follow a few simple
- rules.</p>
-
- <p>First, your ActionForm bean must have a zero-arguments
- constructor. This is required because the framework must be able to
- dynamically create new instances of your form bean class, while
- knowing only the class name. This is not an onerous restriction,
- however, because the framework will also populate your form bean's
- properties (from the request parameters) for you.</p>
-
- <p>Second, the fields of your form bean are made available to the
- framework by supplying public getter and setter methods that
- follow the naming design patterns described in the JavaBeans
- Specification. For most users, that means using the following
- idiom for each of your form bean's properties:</p>
-
- <pre>
- private {type} fieldName;
-
- public {type} getFieldName() {
- return (this.fieldName);
- }
-
- public void setFieldName({type} fieldName) {
- this.fieldName = fieldName;
- }
- </pre>
-
- <p><strong>NOTE</strong> - you <em>MUST</em> obey the capitalization
- conventions shown above for your ActionForm properties to be recognized.
- The property name in this example is "fieldName", and that must also be
- the name of the input field that corresponds to this property. A bean
- property may have a "getter" method and a "setter" method (in a form bean,
- it is typical to have both) whose name starts with "get" or "set",
- followed by the property name with the first character capitalized.
- (For boolean properties, it is also legal to use "is" instead of "get"
- as the prefix for the getter method.)</p>
-
- <p> Advanced JavaBeans users will know that you can tell the system
- you want to use different names for the getter and setter methods, by
- using a <code>java.beans.BeanInfo</code> class associated with your form
- bean. Normally, however, it is much more convenient to follow the
- standard conventions.</p>
-
- <p><strong>WARNING</strong> - developers might be tempted to use one of
- the following techniques, but any of them will cause your property not
- to be recognized by the JavaBeans introspection facilities, and therefore
- cause your applications to misbehave:</p>
- <ul>
- <li><em>Using getter and setter method names that do not
- match</em> - if you have a <code>getFoo()</code> method for your
- getter, but a <code>setBar()</code> method for your setter, Java
- will not recognize these methods as referring to the same property.
- Instead, the language will think you have a read-only property named
- "foo" and a write-only property named "bar".</li>
- <li><em>Using more than one setter method with the same
- name</em> - The Java language lets you "overload" methods, as long
- as the argument types are different. For example, you could have a
- <code>setStartDate(java.util.Date date)</code> method and a
- <code>setStartDate(String date)</code> method in the same class, and
- the compiled code would know which method to call based on the
- parameter type being passed. However, doing this for form bean
- properties will prevent Java from recognizing that you have a
- "startDate" property at all.</li>
- </ul>
-
- <p>There are other rules to follow if you want other features of your
- form beans to be exposed. These include indexed attributes and mapped
- attributes. They are covered in detail in other areas of the
- documentation, in particular:</p>
-
- <a href="indexedprops.html">indexedprops.html</a>
-
-
- <p>For a complete explanation of what a JavaBean is, and everything it can
- do, see the JavaBeans Specification (version 1.01) at:</p>
-
- <a href="http://java.sun.com/products/javabeans/docs/beans.101.pdf">
- http://java.sun.com/products/javabeans/docs/beans.101.pdf</a>
-
-
-</subsection>
-
-<a name="separate"/>
-<subsection name="Do I have to have a separate ActionForm bean for every HTML form?">
-
- <p>This is an interesting question. As a newbie, it is a good
- practice to create a new <code>ActionForm</code> for each action
- sequence. You can use <code>DynaActionForm</code>s to help reduce
- the effort required, or use the code generation facilities of your
- IDE.</p>
-
- <p>Some issues to keep in mind regarding reuse of form beans
- are as follows:</p>
- <ul>
- <li><em>Validation</em> - You might need to use different
- validation rules depending upon the action that is currently
- being executed.</li>
- <li><em>Persistence</em> - Be careful that a form populated in
- one action is not <strong>unexpectedly</strong> reused in a
- different action. Multiple <code><form-bean></code>
- entries in <code>struts-config.xml</code> for the same
- <code>ActionForm</code> subclass can help (especially if you
- store your form beans in session scope). Alternatively,
- storing form beans in request scope can avoid unexpected
- interactions (as well as reduce the memory footprint of your
- application, because no server-side objects will need to be
- saved in between requests.</li>
- <li><em>Checkboxes</em> - If you do as recommended and reset
- your boolean properties (for fields presented as checkboxes),
- and the page you are currently displaying does not have a
- checkbox for every boolean property on the form bean, the
- undisplayed boolean properties will always appear to have a
- <code>false</code> value.</li>
- <li><em>Workflow</em> - The most common need for form bean
- reuse is workflow. Out of the box, the framework has limited support
- for workflow, but a common pattern is to use a single form bean
- with all of the properties for all of the pages of a workflow.
- You will need a good understanding of the
- environment (<code>ActionForm</code>s, <code>Action</code>s,
- etc.) prior to being able to put together a smooth workflow
- environment using a single form bean.</li>
- </ul>
-
- <p>As you get more comfortable, there are a few shortcuts you can
- take in order to reuse your <code>ActionForm</code> beans. Most of
- these shortcuts depend on how you have chosen to implement your
- <code>Action</code> / <code>ActionForm</code> combinations.</p>
-
-</subsection>
-
-<a name="prepopulate"/>
-<subsection name="How can I prepopulate a form?">
-
- <p>The simplest way to prepopulate a form is to have an <code>Action</code>
- whose sole purpose is to populate an <code>ActionForm</code> and forward
- to the servlet or JSP to render that form back to the client. A separate
- <code>Action</code> would then be use to process the submitted form fields,
- by declaring an instance of the same form bean name.</p>
-
- <p>The <em>MailReader</em> application, part of the Struts Applications
- subrpoject, illustrates this design pattern nicely. Note the following
- definitions from the <code>struts-config.xml</code> file:</p>
- <pre>
- ...
- <form-beans>
- ...
- <-- Registration form bean -->
- <form-bean name="registrationForm"
- type="org.apache.struts.webapp.example.RegistrationForm"/>
- ...
- </form-beans>
- ...
- <action-mappings>
- ...
- <-- Edit user registration -->
- <action path="/editRegistration"
+ <properties>
+ <title>Newbie FAQ</title>
+ </properties>
+ <body>
+ <section href="faq" name="Newbie FAQ">
+
+ <a name="contents"/>
+ <subsection name="Index">
+
+ <p>
+ Here are answers to the most common questions people ask
+ when using
+ the framework on their first project.
+ </p>
+
+ <ul>
+
+ <li>
+ <a href="#modules">What is a modular application? What
+ does
+ module-relative mean?</a>
+ </li>
+
+ <li>
+ <a href="#naming">Why are some of the class and
+ element names
+ counter-intuitive?</a>
+ </li>
+
+ <li>
+ <a href="#actionForms">Whither ActionForms?</a>
+ </li>
+
+ <li>
+ <a href="#actionFormInterface">Why is ActionForm a
+ base class rather than an interface?</a>
+ </li>
+
+ <li>
+ <a href="#news">Can I use other beans or hashmaps with
+ ActionForms?</a>
+ </li>
+
+ <li>
+ <a href="#authenticate">How can I authenticate my
+ users?</a>
+ </li>
+
+ <li>
+ <a href="#jsp">Do I have to use JSPs with my
+ application?</a>
+ </li>
+
+ <li>
+ <a href="#formbeans">Do ActionForms have to be true
+ JavaBeans?</a>
+ </li>
+
+ <li>
+ <a href="#separate">Do I have to have a separate
+ ActionForm bean
+ for every HTML form?</a>
+ </li>
+
+ <li>
+ <a href="#prepopulate">How can I prepopulate a
+ form?</a>
+ </li>
+
+ <li>
+ <a href="#noForm">Can I have an Action without a
+ form?</a>
+ </li>
+
+ <li>
+ <a href="#requiredif">Can you give me a simple example
+ of using the requiredif Validator rule?</a>
+ </li>
+
+ <li>
+ <a href="#validate">When is the best time to validate
+ input?</a>
+ </li>
+
+ <li>
+ <a href="#avoidValidate">How can I avoid validating a
+ form before data is entered?</a>
+ </li>
+
+ <li>
+ <a href="#wizard">How can I create a "wizard"
+ workflow?</a>
+ </li>
+
+ <li>
+ <a href="#chaining">How can I "chain" Actions?</a>
+ </li>
+
+ </ul>
+
+ <p>
+ If you like to
+ <a href="helping.html">contribute</a>
+ ,
+ there is a list of
+ <a href="#undocumented">undocumented questions</a>
+ at the end of this page.
+ </p>
+
+ </subsection>
+
+
+ <a name="modules"/>
+ <subsection
+ name="What is a modular application? What does module-relative mean?">
+
+ <p>
+ Since Struts 1.1, the framework supports multiple
+ application modules. All applications have at
+ least one root, or default, module. Like the root
+ directory in a file system, the default application
+ has no name. (Or is named with an empty string, depending
+ your viewpoint.) Developing an application
+ with only a default module is no different from how
+ applications were developed under Struts 1.0.
+ Since Struts 1.1, you can add additional modules to your
+ application, each of which can have their
+ own configuration files, messages resources, and so forth.
+ Each module is developed in the same way as
+ the default module. Applications that were developed as a
+ single module can added to a multiple
+ module application, and modules can promoted to a
+ standalone application without change. For more
+ about configuring your application to support multiple
+ modules, see
+ <a href="../userGuide/configuration.html#dd_config_modules">
+ Configuring Applications</a>
+ in the
+ User Guide.
+ </p>
+
+ <p>
+ But to answer the question =:0), a modular application is
+ an application that uses more than
+ one module. Module-relative means that the URI starts at
+ the module level, rather than at
+ the context level, or the absolute-URL level.
+ </p>
+ <ul>
+ <li>Absolute URL:
+ http://localhost/myApplication/myModule/myAction.do</li>
+ <li>context-relative: /myModule/myAction.do</li>
+ <li>module-relative: /myAction.do</li>
+ </ul>
+
+ <p>
+ The Struts Examples application is a modular application
+ that was assembled from several
+ applications that were created independently.
+ </p>
+
+ </subsection>
+
+ <a name="naming"/>
+ <subsection
+ name="Why are some of the class and element names counter-intuitive?">
+ <p>
+ The framework grew in the telling and, as it evolved, some
+ of the names
+ drifted.
+ </p>
+ <p>The good thing about a nightly build, is that everything
+ becomes
+ available to the community as soon as it is written. The
+ bad thing about
+ a nightly build is that things like class names get locked
+ down early and
+ then become difficult to change.
+ </p>
+ </subsection>
+
+ <a name="actionForms"/>
+ <subsection name="Whither ActionForms?">
+ <p>
+ <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19281.html">
+ http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19281.html</a>
+ <br/>
+ <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html">
+ http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html</a>
+ <br/>
+ <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg20833.html">
+ http://www.mail-archive.com/struts-user@jakarta.apache.org/msg20833.html</a>
+ <br/>
+ </p>
+ </subsection>
+
+ <a name="actionFormInterface"/>
+ <subsection
+ name="Why is ActionForm a base class rather than an interface?">
+ <p>
+ Originally, the rationale as that making ActionForm a
+ class takes advantage of the single
+ inheritance restriction of Java to it makes it more
+ difficult for people to do
+ things that they should not do. At the time, EJBs were
+ becoming popular, and
+ most developers were trying to combine EJB remoting with
+ ActionForms,
+ and the result was not pretty.
+ </p>
+ <p>
+ Since then, most developers use different approaches to
+ data persistent,
+ and most developers now have a good understanding of why
+ we want to separate
+ the model from the view.
+ Accordingly, we do plan to introduce more interfaces into
+ the framework.
+ It's just a matter of when.
+ </p>
+ <p>
+ Meanwhile, DynaActionForms relieve developers of
+ maintaining simple ActionForms.
+ For near zero maintenance, try
+ <a href="http://www.niallp.pwp.blueyonder.co.uk/">
+ LazyActionForm</a>
+ and Hubert Rabago's
+ <a href="https://formdef.dev.java.net/">FormDef</a>
+ .
+ </p>
+ </subsection>
+
+ <a name="JavaBeans"/>
+ <subsection name="Do ActionForms have to be true JavaBeans?">
+ <p>
+ The utilities that the framework uses (Commons-BeanUtils
+ since 1.1) require that ActionForm properties follow
+ the JavaBean patterns for mutators and accessors
+ (get*,set*,is*). Since the framework uses the
+ Introspection API
+ with the ActionForms, some containers may require that all
+ the JavaBean patterns be followed, including
+ declaring "
+ <code>implements Serializable</code>
+ " for each subclass. The safest thing is to review the
+ <a href="../userGuide/preface.html#javabeans">JavaBean
+ specification</a>
+ and follow all the prescribed patterns.
+ </p>
+ <p>
+ Since Struts 1.1, you can also use DynaActionForms and
+ mapped-backed forms, which are not true JavaBeans.
+ For more see
+ <a href="../userGuide/building_controller.html#action_form_classes">
+ ActionForm classes</a>
+ in the User Guide
+ and
+ <a href="#otherBeans">Using Hashmaps with ActionForms</a>
+ in this FAQ.
+ </p>
+ </subsection>
+
+ <a name="otherBeans"/>
+ <subsection
+ name="Can I use other beans or hashmaps with ActionForms?">
+ <p>
+ Yes. There are several ways that you can use other beans
+ or hashmaps with ActionForms.
+ </p>
+ <ul>
+ <li>
+ ActionForms can have other beansor hashmaps as
+ properties
+ </li>
+ <li>
+ "Value Beans" or "Data Transfer Objects" (DTOs) can be
+ used independently of
+ ActionForms to transfer data to the view
+ </li>
+ <li>
+ ActionForms can use Maps to support "dynamic"
+ properties (since Struts 1.1)
+ </li>
+ </ul>
+ <p>
+ ActionForms (a.k.a. "form beans") are really just Java
+ beans (with a few
+ special methods) that the framework creates and puts into
+ session or request scope for you.
+ There is nothing preventing you from using other beans, or
+ including
+ them in your form beans. Here are some examples:
+ </p>
+ <p>
+ <em>Collections as properties</em>
+ Suppose that you need to display a pulldown list of
+ available colors on an input form in your application. You
+ can include a string-valued
+ <code>colorSelected</code>
+ property in your
+ <code>ActionForm</code>
+ to represent the user's
+ selection and a
+ <code>colorOptions</code>
+ property implemented as a
+ <code>Collection</code>
+ (of strings) to store the available color choices.
+ Assuming that you have defined the getters
+ and setters for the
+ <code>colorSelected</code>
+ and
+ <code>colorOptions</code>
+ properties
+ in your
+ <code>orderEntryForm</code>
+ form bean, you can render the
+ pulldown list using:
+ </p>
+ <source>
+ <html:select property="colorSelected">
+ <html:options property="colorOptions"
+ name="orderEntryForm"/>
+ </html:select>
+ </source>
+ <p>
+ The list will be populated using the strings in the
+ <code>colorOptions</code>
+ collection of the
+ <code>orderEntryForm</code>
+ and the value that the user selects
+ will go into the
+ <code>colorSelected</code>
+ property that gets posted to the subsequent
+ <code>Action</code>
+ . Note that we are assuming here that the
+ <code>colorOptions</code>
+ property of the
+ <code>orderEntryForm</code>
+ has already been set.
+ </p>
+ <p>
+ See
+ <a href="#prepopulate">How can I prepopulate a form?</a>
+ for instructions on how to set
+ form bean properties before rendering edit forms that
+ expect properties to be pre-set.
+ </p>
+ <p>
+ <em>Independent DTO</em>
+ An
+ <code>Action</code>
+ that retrieves a list of open orders (as an
+ <code>ArrayList</code>
+ of
+ <code>Order</code>
+ objects) can use a DTO independently of any
+ form bean to transfer search results to the view. First,
+ the Action's
+ <code>execute</code>
+ method performs the search and puts the DTO into the
+ request:
+ </p>
+ <source>
+ ArrayList results =
+ businessObject.executeSearch(searchParameters);
+ request.setAttribute("searchResults",results);
+ </source>
+ <p>
+ Then the view can iterate through the results using the
+ "searchResults" request key to
+ reference the DTO:
+ `</p>
+ <source>
+ <logic:iterate id="order" name="searchResults"
+ type="com.foo.bar.Order">
+ <tr><td><bean:write name="order"
+ property="orderNumber"/><td>
+ <td>..other properties...</td></tr>
+ </logic:iterate>
+ </source>
+ <p>
+ See also:
+ <a href="../userGuide/building_controller.html#map_action_form_classes">
+ Map-Backed ActionForms</a>
+ (since Struts 1.1)
+ </p>
+ </subsection>
+
+ <a name="authenticate"/>
+ <subsection name="How can I authenticate my users?">
+ <p>
+ <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24504.html">
+ http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24504.html</a>
+ <br/>
+ <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22949.html">
+ http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22949.html</a>
+ </p>
+ </subsection>
+
+ <a name="jsp"/>
+ <subsection name="Do I have to use JSPs with my application?">
+
+ <p>
+ The short answer to this question is: No, you are not
+ limited to
+ JavaServer Pages.
+ </p>
+
+ <p>
+ The longer answer is that you can use any type of
+ presentation technology
+ which can be returned by a web server or Java container.
+ The list includes but is not limited to:
+ </p>
+
+ <ul>
+
+ <li>
+ JavaServer Pages,
+ </li>
+
+ <li>
+ HTML pages,
+ </li>
+
+ <li>
+ WML files,
+ </li>
+
+ <li>
+ Java servlets,
+ </li>
+
+ <li>
+ Velocity templates, and
+ </li>
+
+ <li>
+ XML/XLST
+ </li>
+
+ </ul>
+
+ <p>
+ Some people even mix and match apparently unrelated
+ technologies,
+ like PHP, into the same web application.
+ </p>
+
+ </subsection>
+
+ <a name="formbeans"/>
+ <subsection name="Do ActionForms have to be true JavaBeans?">
+
+ <p>ActionForms are added to a servlet scope (session or
+ request)
+ as beans. What this means is that, for certain
+ functionality to
+ be available, your ActionForms will have to follow a few
+ simple
+ rules.</p>
+
+ <p>First, your ActionForm bean must have a zero-arguments
+ constructor. This is required because the framework must
+ be able to
+ dynamically create new instances of your form bean class,
+ while
+ knowing only the class name. This is not an onerous
+ restriction,
+ however, because the framework will also populate your
+ form bean's
+ properties (from the request parameters) for you.</p>
+
+ <p>Second, the fields of your form bean are made available to
+ the
+ framework by supplying public getter and setter methods
+ that
+ follow the naming design patterns described in the
+ JavaBeans
+ Specification. For most users, that means using the
+ following
+ idiom for each of your form bean's properties:</p>
+
+ <pre>
+ private {type} fieldName;
+
+ public {type} getFieldName() {
+ return (this.fieldName);
+ }
+
+ public void setFieldName({type} fieldName) {
+ this.fieldName = fieldName;
+ }
+ </pre>
+
+ <p>
+ <strong>NOTE</strong>
+ - you
+ <em>MUST</em>
+ obey the capitalization
+ conventions shown above for your ActionForm properties to
+ be recognized.
+ The property name in this example is "fieldName", and that
+ must also be
+ the name of the input field that corresponds to this
+ property. A bean
+ property may have a "getter" method and a "setter" method
+ (in a form bean,
+ it is typical to have both) whose name starts with "get"
+ or "set",
+ followed by the property name with the first character
+ capitalized.
+ (For boolean properties, it is also legal to use "is"
+ instead of "get"
+ as the prefix for the getter method.)
+ </p>
+
+ <p>Advanced JavaBeans users will know that you can tell the
+ system
+ you want to use different names for the getter and setter
+ methods, by
+ using a
+ <code>java.beans.BeanInfo</code>
+ class associated with your form
+ bean. Normally, however, it is much more convenient to
+ follow the
+ standard conventions.
+ </p>
+
+ <p>
+ <strong>WARNING</strong>
+ - developers might be tempted to use one of
+ the following techniques, but any of them will cause your
+ property not
+ to be recognized by the JavaBeans introspection
+ facilities, and therefore
+ cause your applications to misbehave:
+ </p>
+ <ul>
+ <li>
+ <em>Using getter and setter method names that do not
+ match</em>
+ - if you have a
+ <code>getFoo()</code>
+ method for your
+ getter, but a
+ <code>setBar()</code>
+ method for your setter, Java
+ will not recognize these methods as referring to the
+ same property.
+ Instead, the language will think you have a read-only
+ property named
+ "foo" and a write-only property named "bar".
+ </li>
+ <li>
+ <em>Using more than one setter method with the same
+ name</em>
+ - The Java language lets you "overload" methods, as
+ long
+ as the argument types are different. For example, you
+ could have a
+ <code>setStartDate(java.util.Date date)</code>
+ method and a
+ <code>setStartDate(String date)</code>
+ method in the same class, and
+ the compiled code would know which method to call
+ based on the
+ parameter type being passed. However, doing this for
+ form bean
+ properties will prevent Java from recognizing that you
+ have a
+ "startDate" property at all.
+ </li>
+ </ul>
+
+ <p>There are other rules to follow if you want other features
+ of your
+ form beans to be exposed. These include indexed attributes
+ and mapped
+ attributes. They are covered in detail in other areas of
+ the
+ documentation, in particular:</p>
+
+ <a href="indexedprops.html">indexedprops.html</a>
+
+
+ <p>For a complete explanation of what a JavaBean is, and
+ everything it can
+ do, see the JavaBeans Specification (version 1.01) at:</p>
+
+ <a href="http://java.sun.com/products/javabeans/docs/beans.101.pdf">
+ http://java.sun.com/products/javabeans/docs/beans.101.pdf</a>
+
+
+ </subsection>
+
+ <a name="separate"/>
+ <subsection
+ name="Do I have to have a separate ActionForm bean for every HTML form?">
+
+ <p>This is an interesting question. As a newbie, it is a good
+ practice to create a new
+ <code>ActionForm</code>
+ for each action
+ sequence. You can use
+ <code>DynaActionForm</code>
+ s to help reduce
+ the effort required, or use the code generation facilities
+ of your
+ IDE.
+ </p>
+
+ <p>Some issues to keep in mind regarding reuse of form beans
+ are as follows:</p>
+ <ul>
+ <li>
+ <em>Validation</em>
+ - You might need to use different
+ validation rules depending upon the action that is
+ currently
+ being executed.
+ </li>
+ <li>
+ <em>Persistence</em>
+ - Be careful that a form populated in
+ one action is not
+ <strong>unexpectedly</strong>
+ reused in a
+ different action. Multiple
+ <code><form-bean></code>
+ entries in
+ <code>struts-config.xml</code>
+ for the same
+ <code>ActionForm</code>
+ subclass can help (especially if you
+ store your form beans in session scope).
+ Alternatively,
+ storing form beans in request scope can avoid
+ unexpected
+ interactions (as well as reduce the memory footprint
+ of your
+ application, because no server-side objects will need
+ to be
+ saved in between requests.
+ </li>
+ <li>
+ <em>Checkboxes</em>
+ - If you do as recommended and reset
+ your boolean properties (for fields presented as
+ checkboxes),
+ and the page you are currently displaying does not
+ have a
+ checkbox for every boolean property on the form bean,
+ the
+ undisplayed boolean properties will always appear to
+ have a
+ <code>false</code>
+ value.
+ </li>
+ <li>
+ <em>Workflow</em>
+ - The most common need for form bean
+ reuse is workflow. Out of the box, the framework has
+ limited support
+ for workflow, but a common pattern is to use a single
+ form bean
+ with all of the properties for all of the pages of a
+ workflow.
+ You will need a good understanding of the
+ environment (
+ <code>ActionForm</code>
+ s,
+ <code>Action</code>
+ s,
+ etc.) prior to being able to put together a smooth
+ workflow
+ environment using a single form bean.
+ </li>
+ </ul>
+
+ <p>As you get more comfortable, there are a few shortcuts you
+ can
+ take in order to reuse your
+ <code>ActionForm</code>
+ beans. Most of
+ these shortcuts depend on how you have chosen to implement
+ your
+ <code>Action</code>
+ /
+ <code>ActionForm</code>
+ combinations.
+ </p>
+
+ </subsection>
+
+ <a name="prepopulate"/>
+ <subsection name="How can I prepopulate a form?">
+
+ <p>The simplest way to prepopulate a form is to have an
+ <code>Action</code>
+ whose sole purpose is to populate an
+ <code>ActionForm</code>
+ and forward
+ to the servlet or JSP to render that form back to the
+ client. A separate
+ <code>Action</code>
+ would then be use to process the submitted form fields,
+ by declaring an instance of the same form bean name.
+ </p>
+
+ <p>The
+ <em>MailReader</em>
+ application, part of the Struts Applications
+ subrpoject, illustrates this design pattern nicely. Note
+ the following
+ definitions from the
+ <code>struts-config.xml</code>
+ file:
+ </p>
+ <pre>
+ ...
+ <form-beans>
+ ...
+ <-- Registration form bean -->
+ <form-bean name="registrationForm"
+ type="org.apache.struts.webapp.example.RegistrationForm"/>
+ ...
+ </form-beans>
+ ...
+ <action-mappings>
+ ...
+ <-- Edit user registration -->
+ <action path="/editRegistration"
type="org.apache.struts.webapp.example.EditRegistrationAction"
name="registrationForm"
- scope="request"
- validate="false"/>
- ...
- <-- Save user registration -->
- <action path="/saveRegistration"
+ scope="request"
+ validate="false"/>
+ ...
+ <-- Save user registration -->
+ <action path="/saveRegistration"
type="org.apache.struts.webapp.example.SaveRegistrationAction"
name="registrationForm"
- input="registration"
- scope="request"/>
- ...
- </action-mappings>
- </pre>
-
- <p>Note the following features of this approach:</p>
- <ul>
- <li>Both the <code>/editRegistration</code> and
- <code>/saveRegistration</code> actions use the same form bean.</li>
- <li>When the <code>/editRegistration</code> action is entered, the
- framework will have pre-created an empty form bean instance, and passed it to
- the <code>execute()</code> method. The setup action is free to
- preconfigure the values that will be displayed when the form is
- rendered, simply by setting the corresponding form bean properties.
- </li>
- <li>When the setup action completes configuring the properties of the
- form bean, it should return an <code>ActionForm</code> that points
- at the page which will display this form. If you are using the
- Struts JSP tag library, the <code>action</code> attribute on your
- <html:form> tag will be set to <code>/saveRegistration</code>
- in order for the form to be submitted to the processing action.</li>
- <li>Note that the setup action (<code>/editRegistration</code>) turns off
- validation on the form that is being set up. You will normally want
- to include this attribute in the configuration of your setup actions,
- because you are not planning to actually process the results -- you
- simply want to take advantage of the fact that the framework will precreate
- a form bean instance of the correct class for you.</li>
- <li>The processing action (<code>/saveRegistration</code>), on the other
- hand, leaves out the <code>validate</code> attribute, which defaults
- to <code>true</code>. This tells the framework to perform the validations
- associated with this form bean before invoking the processing action
- at all. If any validation errors have occurred, the framework will forward
- back to your input page (technically, it forwards back to an
- <code>ActionForward</code> named "registration" in this case, because
- the example webapp uses the <code>inputForward</code> attribute in the
- <code><controller></code> element -- see the documentation
- describing <code>struts-config.xml</code> for more information)
- instead of calling your processing action.</li>
- </ul>
-
-</subsection>
-
-<a name="noForm"/>
-<subsection name="Can I have an Action without a form?">
-<p>
-Yes. If your <code>Action</code> does not need any data and it does not need to make any
-data available to the view or controller component that it forwards to, it doesn't need
-a form. A good example of an <code>Action</code> with no <code>ActionForm</code> is the
-<code>LogoffAction</code> in the Struts MailReader application:</p>
-<pre>
- <action path="/logoff"
- type="org.apache.struts.webapp.example.LogoffAction">
- <forward name="success" path="/index.jsp"/>
- </action>
-</pre>
-<p>
-This action needs no data other than the user's session, which it can get from the
-<code>Request</code>, and it doesn't need to prepare any view elements for display,
-so it does not need a form.
-</p>
-
- <p>
- However, you cannot use the <html:form> <strong>tag</strong> without an ActionForm.
- Even if you want to use the <html:form> tag with a simple Action that does not require input,
- the tag will expect you to use some type of ActionForm, even if it is an empty subclass without any properties.
- </p>
-
-</subsection>
-
-<a name="requiredif"/>
-<subsection name="Can you give me a simple example of using the requiredif Validator rule?">
- <p>First off, there's an even newer Validator rule called <code>validwhen</code>,
- which is almost certainly what you want to use, since it is much easier and
- more powerful. It will be available in the first release after 1.1 ships.
- The example shown below could be coded with validwhen as:</p>
-<pre>
-<form name="medicalStatusForm">
-
-<field
- property="pregnancyTest" depends="validwhen">
- <arg0 key="medicalStatusForm.pregnancyTest.label"/>
- <var>
- <var-name>test</var-name>
- <var-value>((((sex == 'm') OR (sex == 'M')) AND (*this* == null)) OR (*this* != null))</test>
- </var>
-</field>
-</pre>
- <p>Let's assume you have a medical information form with three fields, sex, pregnancyTest, and testResult.
- If sex is 'f' or 'F', pregnancyTest is required. If pregnancyTest is not blank, testResult is required.
- The entry in your validation.xml file would look like this:
- </p>
- <pre>
-<form name="medicalStatusForm">
-
-<field
- property="pregnancyTest" depends="requiredif">
- <arg0 key="medicalStatusForm.pregnancyTest.label"/>
- <var>
- <var-name>field[0]</var-name>
- <var-value>sex</var-value>
- </var>
- <var>
- <var-name>fieldTest[0]</var-name>
- <var-value>EQUAL</var-value>
- </var>
- <var>
- <var-name>fieldValue[0]</var-name>
- <var-value>F</var-value>
- </var>
- <var>
- <var-name>field[1]</var-name>
- <var-value>sex</var-value>
- </var>
- <var>
- <var-name>fieldTest[1]</var-name>
- <var-value>EQUAL</var-value>
- </var>
- <var>
- <var-name>fieldValue[1]</var-name>
- <var-value>f</var-value>
- </var>
- <var>
- <var-name>fieldJoin</var-name>
- <var-value>OR</var-value>
- </var>
-</field>
-
-<field
- property="testResult" depends="requiredif">
- <arg0 key="medicalStatusForm.testResult.label"/>
- <var>
- <var-name>field[0]</var-name>
- <var-value>pregnancyTest</var-value>
- </var>
- <var>
- <var-name>fieldTest[0]</var-name>
- <var-value>NOTNULL</var-value>
- </var>
-</field>
-</form>
-</pre>
-</subsection>
-
-<a name="validate"/>
-<subsection name="When is the best time to validate input?">
-<p>
-This is an excellent question. Let's step back a second and think about a
-typical mid to large size application. If we start from the back end and work
-toward the view we have:
-</p>
-<p>
-1) Database: Most modern databases are going to validate for required
-fields, duplicate records, security constraints, etc.</p>
-<p>
-2) Business Logic: Here you are going to check for valid data relationships
-and things that make sense for the particular problem you are triing to
-solve.</p>
-<p>
-... This is where the framework comes into the picture, by now the system should be
-pretty well bulletproof. What we are going to do is make validation friendlier
-and informative. Rember it is OK to have duplicate validations...</p>
-<p>
-3) <code>ActionErrors validate(ActionMapping map, HttpServletRequest req)</code>
-is where you can do your validation and feed back to the view,
-information required to correct any errors. <code>validate</code> is run after
-the form has been <code>reset</code> and after the <code>ActionForm</code>
-properties have been set from corresponding view based input. Also remember you
-can turn validation off with <code>validate="false"</code> in the
-<code>action</code> mapping in the <code>struts-config.xml</code>. This is done
-by returning an <code>ActionErrors</code> collection with messages from your
-<code>ApplicationResources.properties</code> file.</p>
-<p>
-Here you have access to the request so you can see what kinds of action is
-being requested to fine tune your validations. The <html:error> tag
-allows you to dump all errors on your page or a particular error associated
-with a particular property. The <code>input</code> attribute of the
-<code>struts-config.xml</code> <code>action</code> allows you to send
-validation errors to a particular jsp / html / tile page.</p>
-<p>
-4) You can have the system perform low level validations and client side
-feedback using a <code>ValidatorForm</code> or its derivatives. This will
-generate javascript and give instant feedback to the user for simple data entry
-errors. You code your validations in the <code>validator-rules.xml</code>
-file. A working knowledge of
-<a href="http://etext.lib.virginia.edu/helpsheets/regex.html">regular
-expressions</a> is necessary to use this feature effectively. For more
-information, see
-<a href="../userGuide/dev_validator.html">
-User Guide</a></p>
-</subsection>
-
-<a name="avoidValidate"/>
-<subsection
- name="How can I avoid validating a form before data is entered?">
- <p>
- The simplest way is to have two actions. The first one has the job of setting
- the form data, i.e. a blank registration screen. The second action in our
- writes the registration data to the database. The framework
- would take care of invoking the validation and returning the user to the
- correct screen if validation was not complete.
- </p>
-
- <p>
- The EditRegistration action in the Struts MailReader application illustrates this:
- </p>
-
- <source>
- <action path="/editRegistration"
- type="org.apache.struts.webapp.example.EditRegistrationAction"
- attribute="registrationForm"
- scope="request"
- validate="false">
- <forward name="success path="/registration.jsp"/>
- </action>
- </source>
-
-<p>
-When the /editRegistration action is invoked, a registrationForm is created and added to the request,
-but its validate method is not called. The default value of the <code>validate</code> attribute is
-<code>true</code>, so if you do not want an action to trigger form validation, you need to remember
-to add this attribute and set it to <code>false</code>.
-</p>
-
-</subsection>
-
-<a name="wizard"/>
-<subsection name="How can I create a wizard workflow?">
- <p>
- The basic idea is a series of actions with next, back, cancel
- and finish actions with a common bean. Using a LookupDispatchAction is
- reccomended as it fits the design pattern well and can be internationalized
- easily. Since the bean is shared, each choice made will add data to the
- wizards base of information. A sample of struts-config.xml follows:
- </p>
-
- <source>
- <form-beans>
- <form-bean name="MyWizard"
- type="forms.MyWizard" />
- </form-beans>
-
- <!-- the first screen of the wizard (next action only available) -->
- <!-- no validation, since the finish action is not available -->
- <actions>
- <action path="/mywizard1"
- type="actions.MyWizard"
- name="MyWizard"
- validate="false"
- input="/WEB-INF/jsp/mywizard1.jsp">
+ input="registration"
+ scope="request"/>
+ ...
+ </action-mappings>
+ </pre>
+
+ <p>Note the following features of this approach:</p>
+ <ul>
+ <li>Both the
+ <code>/editRegistration</code>
+ and
+ <code>/saveRegistration</code>
+ actions use the same form bean.
+ </li>
+ <li>When the
+ <code>/editRegistration</code>
+ action is entered, the
+ framework will have pre-created an empty form bean
+ instance, and passed it to
+ the
+ <code>execute()</code>
+ method. The setup action is free to
+ preconfigure the values that will be displayed when
+ the form is
+ rendered, simply by setting the corresponding form
+ bean properties.
+ </li>
+ <li>When the setup action completes configuring the
+ properties of the
+ form bean, it should return an
+ <code>ActionForm</code>
+ that points
+ at the page which will display this form. If you are
+ using the
+ Struts JSP tag library, the
+ <code>action</code>
+ attribute on your
+ <html:form> tag will be set to
+ <code>/saveRegistration</code>
+ in order for the form to be submitted to the
+ processing action.
+ </li>
+ <li>Note that the setup action (
+ <code>/editRegistration</code>
+ ) turns off
+ validation on the form that is being set up. You will
+ normally want
+ to include this attribute in the configuration of your
+ setup actions,
+ because you are not planning to actually process the
+ results -- you
+ simply want to take advantage of the fact that the
+ framework will precreate
+ a form bean instance of the correct class for you.
+ </li>
+ <li>The processing action (
+ <code>/saveRegistration</code>
+ ), on the other
+ hand, leaves out the
+ <code>validate</code>
+ attribute, which defaults
+ to
+ <code>true</code>
+ . This tells the framework to perform the validations
+ associated with this form bean before invoking the
+ processing action
+ at all. If any validation errors have occurred, the
+ framework will forward
+ back to your input page (technically, it forwards back
+ to an
+ <code>ActionForward</code>
+ named "registration" in this case, because
+ the example webapp uses the
+ <code>inputForward</code>
+ attribute in the
+ <code><controller></code>
+ element -- see the documentation
+ describing
+ <code>struts-config.xml</code>
+ for more information)
+ instead of calling your processing action.
+ </li>
+ </ul>
+
+ </subsection>
+
+ <a name="noForm"/>
+ <subsection name="Can I have an Action without a form?">
+ <p>
+ Yes. If your
+ <code>Action</code>
+ does not need any data and it does not need to make any
+ data available to the view or controller component that it
+ forwards to, it doesn't need
+ a form. A good example of an
+ <code>Action</code>
+ with no
+ <code>ActionForm</code>
+ is the
+ <code>LogoffAction</code>
+ in the Struts MailReader application:
+ </p>
+ <pre>
+ <action path="/logoff"
+ type="org.apache.struts.webapp.example.LogoffAction">
+ <forward name="success" path="/index.jsp"/>
+ </action>
+ </pre>
+ <p>
+ This action needs no data other than the user's session,
+ which it can get from the
+ <code>Request</code>
+ , and it doesn't need to prepare any view elements for
+ display,
+ so it does not need a form.
+ </p>
+
+ <p>
+ However, you cannot use the <html:form>
+ <strong>tag</strong>
+ without an ActionForm.
+ Even if you want to use the <html:form> tag with a
+ simple Action that does not require input,
+ the tag will expect you to use some type of ActionForm,
+ even if it is an empty subclass without any properties.
+ </p>
+
+ </subsection>
+
+ <a name="requiredif"/>
+ <subsection
+ name="Can you give me a simple example of using the requiredif Validator rule?">
+ <p>First off, there's an even newer Validator rule called
+ <code>validwhen</code>
+ ,
+ which is almost certainly what you want to use, since it
+ is much easier and
+ more powerful. It will be available in the first release
+ after 1.1 ships.
+ The example shown below could be coded with validwhen as:
+ </p>
+ <pre>
+ <form name="medicalStatusForm">
+
+ <field
+ property="pregnancyTest" depends="validwhen">
+ <arg0 key="medicalStatusForm.pregnancyTest.label"/>
+ <var>
+ <var-name>test</var-name>
+ <var-value>((((sex == 'm') OR (sex == 'M')) AND
+ (*this* == null)) OR (*this* != null))</test>
+ </var>
+ </field>
+ </pre>
+ <p>Let's assume you have a medical information form with three
+ fields, sex, pregnancyTest, and testResult.
+ If sex is 'f' or 'F', pregnancyTest is required. If
+ pregnancyTest is not blank, testResult is required.
+ The entry in your validation.xml file would look like
+ this:
+ </p>
+ <pre>
+ <form name="medicalStatusForm">
+
+ <field
+ property="pregnancyTest" depends="requiredif">
+ <arg0 key="medicalStatusForm.pregnancyTest.label"/>
+ <var>
+ <var-name>field[0]</var-name>
+ <var-value>sex</var-value>
+ </var>
+ <var>
+ <var-name>fieldTest[0]</var-name>
+ <var-value>EQUAL</var-value>
+ </var>
+ <var>
+ <var-name>fieldValue[0]</var-name>
+ <var-value>F</var-value>
+ </var>
+ <var>
+ <var-name>field[1]</var-name>
+ <var-value>sex</var-value>
+ </var>
+ <var>
+ <var-name>fieldTest[1]</var-name>
+ <var-value>EQUAL</var-value>
+ </var>
+ <var>
+ <var-name>fieldValue[1]</var-name>
+ <var-value>f</var-value>
+ </var>
+ <var>
+ <var-name>fieldJoin</var-name>
+ <var-value>OR</var-value>
+ </var>
+ </field>
+
+ <field
+ property="testResult" depends="requiredif">
+ <arg0 key="medicalStatusForm.testResult.label"/>
+ <var>
+ <var-name>field[0]</var-name>
+ <var-value>pregnancyTest</var-value>
+ </var>
+ <var>
+ <var-name>fieldTest[0]</var-name>
+ <var-value>NOTNULL</var-value>
+ </var>
+ </field>
+ </form>
+ </pre>
+ </subsection>
+
+ <a name="validate"/>
+ <subsection name="When is the best time to validate input?">
+ <p>
+ This is an excellent question. Let's step back a second
+ and think about a
+ typical mid to large size application. If we start from
+ the back end and work
+ toward the view we have:
+ </p>
+ <p>
+ 1) Database: Most modern databases are going to validate
+ for required
+ fields, duplicate records, security constraints, etc.</p>
+ <p>
+ 2) Business Logic: Here you are going to check for valid
+ data relationships
+ and things that make sense for the particular problem you
+ are triing to
+ solve.</p>
+ <p>
+ ... This is where the framework comes into the picture, by
+ now the system should be
+ pretty well bulletproof. What we are going to do is make
+ validation friendlier
+ and informative. Rember it is OK to have duplicate
+ validations...</p>
+ <p>
+ 3)
+ <code>ActionErrors validate(ActionMapping map,
+ HttpServletRequest req)</code>
+ is where you can do your validation and feed back to the
+ view,
+ information required to correct any errors.
+ <code>validate</code>
+ is run after
+ the form has been
+ <code>reset</code>
+ and after the
+ <code>ActionForm</code>
+ properties have been set from corresponding view based
+ input. Also remember you
+ can turn validation off with
+ <code>validate="false"</code>
+ in the
+ <code>action</code>
+ mapping in the
+ <code>struts-config.xml</code>
+ . This is done
+ by returning an
+ <code>ActionErrors</code>
+ collection with messages from your
+ <code>ApplicationResources.properties</code>
+ file.
+ </p>
+ <p>
+ Here you have access to the request so you can see what
+ kinds of action is
+ being requested to fine tune your validations. The <html:error>
+ tag
+ allows you to dump all errors on your page or a particular
+ error associated
+ with a particular property. The
+ <code>input</code>
+ attribute of the
+ <code>struts-config.xml</code>
+ <code>action</code>
+ allows you to send
+ validation errors to a particular jsp / html / tile page.
+ </p>
+ <p>
+ 4) You can have the system perform low level validations
+ and client side
+ feedback using a
+ <code>ValidatorForm</code>
+ or its derivatives. This will
+ generate javascript and give instant feedback to the user
+ for simple data entry
+ errors. You code your validations in the
+ <code>validator-rules.xml</code>
+ file. A working knowledge of
+ <a href="http://etext.lib.virginia.edu/helpsheets/regex.html">
+ regular
+ expressions</a>
+ is necessary to use this feature effectively. For more
+ information, see
+ <a href="../userGuide/dev_validator.html">
+ User Guide</a>
+ </p>
+ </subsection>
+
+ <a name="avoidValidate"/>
+ <subsection
+ name="How can I avoid validating a form before data is entered?">
+ <p>
+ The simplest way is to have two actions. The first one has
+ the job of setting
+ the form data, i.e. a blank registration screen. The
+ second action in our
+ writes the registration data to the database. The
+ framework
+ would take care of invoking the validation and returning
+ the user to the
+ correct screen if validation was not complete.
+ </p>
+
+ <p>
+ The EditRegistration action in the Struts MailReader
+ application illustrates this:
+ </p>
+
+ <source>
+ <action path="/editRegistration"
+ type="org.apache.struts.webapp.example.EditRegistrationAction"
+ attribute="registrationForm"
+ scope="request"
+ validate="false">
+ <forward name="success path="/registration.jsp"/>
+ </action>
+ </source>
+
+ <p>
+ When the /editRegistration action is invoked, a
+ registrationForm is created and added to the request,
+ but its validate method is not called. The default value
+ of the
+ <code>validate</code>
+ attribute is
+ <code>true</code>
+ , so if you do not want an action to trigger form
+ validation, you need to remember
+ to add this attribute and set it to
+ <code>false</code>
+ .
+ </p>
+
+ </subsection>
+
+ <a name="wizard"/>
+ <subsection name="How can I create a wizard workflow?">
+ <p>
+ The basic idea is a series of actions with next, back,
+ cancel
+ and finish actions with a common bean. Using a
+ LookupDispatchAction is
+ reccomended as it fits the design pattern well and can be
+ internationalized
+ easily. Since the bean is shared, each choice made will
+ add data to the
+ wizards base of information. A sample of struts-config.xml
+ follows:
+ </p>
+
+ <source>
+ <form-beans>
+ <form-bean name="MyWizard"
+ type="forms.MyWizard" />
+ </form-beans>
+
+ <!-- the first screen of the wizard (next action only
+ available) -->
+ <!-- no validation, since the finish action is not
+ available -->
+ <actions>
+ <action path="/mywizard1"
+ type="actions.MyWizard"
+ name="MyWizard"
+ validate="false"
+ input="/WEB-INF/jsp/mywizard1.jsp">
<forward name="next"
- path="/WEB-INF/jsp/mywizard2.jsp" />
+ path="/WEB-INF/jsp/mywizard2.jsp" />
<forward name="cancel"
- path="/WEB-INF/jsp/mywizardcancel.jsp" />
- </action>
+ path="/WEB-INF/jsp/mywizardcancel.jsp" />
+ </action>
- <!-- the second screen of the wizard (back, next and finish) -->
- <!-- since finish action is available, bean should validated, note
- validation should not necessarily validate if back action requested, you
- might delay validation or do conditional validation -->
- <action path="/mywizard2"
- type="actions.MyWizard"
- name="MyWizard"
- validate="true"
- input="/WEB-INF/jsp/mywizard2.jsp">
+ <!-- the second screen of the wizard (back, next and
+ finish) -->
+ <!-- since finish action is available, bean should
+ validated, note
+ validation should not necessarily validate if back action
+ requested, you
+ might delay validation or do conditional validation -->
+ <action path="/mywizard2"
+ type="actions.MyWizard"
+ name="MyWizard"
+ validate="true"
+ input="/WEB-INF/jsp/mywizard2.jsp">
<forward name="back"
- path="/WEB-INF/jsp/mywizard1.jsp" />
+ path="/WEB-INF/jsp/mywizard1.jsp" />
<forward name="next"
- path="/WEB-INF/jsp/mywizard3.jsp" />
+ path="/WEB-INF/jsp/mywizard3.jsp" />
<forward name="finish"
- path="/WEB-INF/jsp/mywizarddone.jsp" />
+ path="/WEB-INF/jsp/mywizarddone.jsp" />
<forward name="cancel"
- path="/WEB-INF/jsp/mywizardcancel.jsp" />
- </action>
+ path="/WEB-INF/jsp/mywizardcancel.jsp" />
+ </action>
- <!-- the last screen of the wizard (back, finish and cancel only) -->
- <action path="/mywizard3"
- type="actions.MyWizard"
- name="MyWizard"
- validate="true"
- input="/WEB-INF/jsp/mywizard3.jsp">
+ <!-- the last screen of the wizard (back, finish and
+ cancel only) -->
+ <action path="/mywizard3"
+ type="actions.MyWizard"
+ name="MyWizard"
+ validate="true"
+ input="/WEB-INF/jsp/mywizard3.jsp">
<forward name="back"
- path="/WEB-INF/jsp/mywizard2.jsp" />
+ path="/WEB-INF/jsp/mywizard2.jsp" />
<forward name="finish"
- path="/WEB-INF/jsp/mywizarddone.jsp" />
+ path="/WEB-INF/jsp/mywizarddone.jsp" />
<forward name="cancel"
- path="/WEB-INF/jsp/mywizardcancel.jsp" />
- </action>
- </source>
-
- <p>
- The pieces of the wizard are as follows:
- </p>
-
- <p>
- <strong>forms.MyWizard.java</strong> - the form bean holding the information required
- </p>
- <p>
- <strong>actions.MyWizard.java</strong> - the actions of the wizard, note the use of
- LookupDispatchAction allows for one action class with several methods. All the
- real work will be done in the 'finish' method.
- </p>
- <p>
- <strong>mywizard[x].jsp</strong> - the data collection jsp's
- </p>
- <p>
- <strong>mywizarddone.jsp</strong> - the 'success' page
- </p>
- <p>
- <strong>mywizardcancel.jsp</strong> - the 'cancel' page
- </p>
-
-</subsection>
-
- <a name="chaining"/>
- <subsection name="How can I 'chain' Actions?">
- <p>
- Chaining actions can be done by simply using the proper mapping in your
- forward entries in the struts-config.xml file. Assume you had the following
- two classes:
- </p>
- <source><![CDATA[
+ path="/WEB-INF/jsp/mywizardcancel.jsp" />
+ </action>
+ </source>
+
+ <p>
+ The pieces of the wizard are as follows:
+ </p>
+
+ <p>
+ <strong>forms.MyWizard.java</strong>
+ - the form bean holding the information required
+ </p>
+ <p>
+ <strong>actions.MyWizard.java</strong>
+ - the actions of the wizard, note the use of
+ LookupDispatchAction allows for one action class with
+ several methods. All the
+ real work will be done in the 'finish' method.
+ </p>
+ <p>
+ <strong>mywizard[x].jsp</strong>
+ - the data collection jsp's
+ </p>
+ <p>
+ <strong>mywizarddone.jsp</strong>
+ - the 'success' page
+ </p>
+ <p>
+ <strong>mywizardcancel.jsp</strong>
+ - the 'cancel' page
+ </p>
+
+ </subsection>
+
+ <a name="chaining"/>
+ <subsection name="How can I 'chain' Actions?">
+ <p>
+ Chaining actions can be done by simply using the proper
+ mapping in your
+ forward entries in the struts-config.xml file. Assume you
+ had the following
+ two classes:
+ </p>
+ <source><![CDATA[
/* com/AAction.java */
...
@@ -849,7 +1243,7 @@
}
}
]]></source>
- <source><![CDATA[
+ <source><![CDATA[
/* com/BAction.java */
...
@@ -869,12 +1263,13 @@
}
]]></source>
- <p>
- Then you can chain together these two actions with the Struts
- configuration as shown in the following excerpt:
- </p>
+ <p>
+ Then you can chain together these two actions with the
+ Struts
+ configuration as shown in the following excerpt:
+ </p>
- <source><![CDATA[
+ <source><![CDATA[
...
<action-mappings type="org.apache.struts.action.ActionMapping">
<action path="/A"
@@ -892,60 +1287,88 @@
...
]]></source>
- <p>
- Here we are assuming you are using a suffix-based (<code>.do</code>) servlet
- mapping, which is recommended since module support requires it. When you
- send your browser to the web application and name the action
- <code>A.do</code> (i.e. <code>http://localhost:8080/app/A.do</code>) it will
- execute <code>AAction.execute()</code>, which will then forward to the
- "success" mapping.
- </p>
-
- <p>
- This causes the execution of <code>BAction.execute()</code> since the
- <code><forward></code> entry for "success" in the configuration file
- uses the <code>.do</code> suffix.
- </p>
-
- <p>
- Of course it is also possible to chain actions programmatically, but the
- power and ease of being able to "reroute" your web application's structure
- using the XML configuration file is much easier to maintain.
- </p>
-
- <p>
- As a rule, chaining Actions is <strong>not</strong> recommended.
- If your business classes are properly factored, you should be able to call
- whatever methods you need from any Action, without splicing them together
- into a cybernetic Rube Goldberg device.
- </p>
-
- <p>
[... 106 lines stripped ...]
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org