blob: f50082cd00f5288e97de763b44a3cf6bc36001d9 [file] [log] [blame]
<?xml version="1.0"?>
<!--
// ======================================================================== 78
-->
<document url="building_model.html">
<properties>
<title>The Struts User's Guide - Building Model Components</title>
</properties>
<body>
<section name="2. Building Model Components" href="building_model"/>
<section name="2.1 Overview" href="overview">
<p>
Many requirements documents used for building web applications focus on
the <em>View</em>.
However, you should ensure that the processing required for each submitted
request is also clearly defined from the <em>Model's</em> perspective.
In general, the developer of the <em>Model</em> components will be focusing
on the creation of JavaBeans classes that support all of the functional
requirements.
The precise nature of the beans required by a particular application will
vary widely depending on those requirements, but they can generally be
classified into several categories discussed below.
However, a brief review of the concept of "scope" as it relates to beans
and JSP is useful first.
</p>
</section>
<section name="2.2 JavaBeans and Scope" href="javabeans">
<p>
Within a web-based application, JavaBeans can be stored in (and accessed
from) a number of different collections of "attributes".
Each collection has different rules for the lifetime of that collection,
and the visibility of the beans stored there.
Together, the rules defining lifetime and visibility are called the
<em>scope</em> of those beans.
The JavaServer Pages (JSP) Specification defines scope choices using
the following terms (with the equivalent servlet API concept defined in
parentheses):
</p>
<ul>
<li>
<strong>page</strong> - Beans that are visible within a single JSP page,
for the lifetime of the current request.
(Local variables of the <code>service</code> method)
</li>
<li>
<strong>request</strong> - Beans that are visible within a single JSP page,
as well as to any page or servlet that is included in this page,
or forwarded to by this page.
(Request attributes)
</li>
<li>
<strong>session</strong> - Beans that are visible to all JSP pages and
servlets that participate in a particular user session, across one
or more requests.
(Session attributes)
</li>
<li>
<strong>application</strong> - Beans that are visible to all JSP pages and
servlets that are part of a web application.
(Servlet context attributes)
</li>
</ul>
<p>
It is important to remember that JSP pages and servlets in the same
web application share the same sets of bean collections.
For example, a bean stored as a request attribute in a servlet like this:
</p>
<p>
<code>MyCart mycart = new MyCart(...);<br />
request.setAttribute("cart", mycart);
</code>
</p>
<p>
is immediately visible to a JSP page which this servlet forwards to,
using a standard action tag like this:
</p>
<p>
<code>&lt;jsp:useBean id="cart" scope="request"<br />
class="com.mycompany.MyApp.MyCart"/&gt;
</code>
</p>
</section>
<section name="2.3 ActionForm Beans" href="actionform">
<strong>Note:</strong> While ActionForm beans often have properties that
correspond to properties in your Model beans, the form beans themselves
should be considered a Controller component.
As such, they are able to transfer data between the Model and View layers.
<p>
The Struts framework generally assumes that you have defined an
<code>ActionForm</code> bean (that is, a Java class extending the
<code>ActionForm</code> class) for the input forms in your
application.
<code>ActionForm</code> beans are sometimes just called "form beans".
These may be finely-grained objects, so that there is one
bean for each form, or coarsely-grained so that one bean serves
several forms, or even an entire application.
</p>
<p>
If you declare such beans in your Struts
configuration file (see "<a href="building_controller.html#config">
Building the Controller Components</a>"), the Struts controller servlet
will automatically perform the following services for you, before
invoking the appropriate <code>Action</code> method:
</p>
<ul>
<li>
Check for an instance of a bean of the appropriate class, under the appropriate key,
in the appropriate scope (request or session).
</li>
<li>
If there is no such bean instance available, a new one is
automatically created and added to the appropriate scope (request or session).
</li>
<li>
For every request parameter whose name corresponds to the name
of a property in the bean, the corresponding setter method will
be called. This operates in a manner similar to the standard
JSP action <code>&lt;jsp:setProperty&gt;</code> when you use the
asterisk wildcard to select all properties.
</li>
<li>
The updated <code>ActionForm</code> bean will be passed to the
<code>execute</code> method of an <code>Action</code> class
[<code>org.apache.struts.Action</code>], so that the values can
be made available to your system state and business logic beans.
</li>
</ul>
<p>
For more about coding <code>Actions</code> and <code>ActionForm</code>
beans, see the "<a href="building_controller.html">Building
Controller Components</a>" chapter.
</p>
<p>
You should note that a "form", in the sense discussed here, does not
necessarily correspond to a single JSP page in the user interface.
It is common in many applications to have a "form" (from the user's
perspective) that extends over multiple pages.
Think, for example, of the wizard style user interface that is commonly
used when installing new applications.
Struts encourages you to define a single <code>ActionForm</code> bean that
contains properties for all of the fields, no matter which page the field
is actually displayed on.
Likewise, the various pages of the same form should all be submitted to
the same Action Class.
If you follow these suggestions, the page designers can rearrange the
fields among the various pages, often without requiring changes to the
processing logic.
</p>
<p>
Smaller applications may only need a single ActionForm to service all of
its input forms.
Others applications might use a single ActionForm for each major subsystem
of the application.
Some teams might prefer to have a separate ActionForm class for each
distinct input form or workflow.
How many or how few ActionForms to use is entirely up to you.
The framework doesn't care.
</p>
</section>
<section name="2.4 System State Beans" href="system_state">
<p>
The actual state of a system is normally represented as a set of one or
more JavaBeans classes, whose properties define the current state.
A shopping cart system, for example, will include a bean that represents
the cart being maintained for each individual shopper, and will (among
other things) include the set of items that the shopper has currently
selected for purchase.
Separately, the system will also include different beans for the user's
profile information (including their credit card and ship-to addresses),
as well as the catalog of available items and their current inventory
levels.
</p>
<p>
For small scale systems, or for state information that need not be kept
for a long period of time, a set of system state beans may contain all the
knowledge that the system ever has of these particular details.
Or, as is often the case, the system state beans will represent
information that is stored permanently in some external database (such as
a <code>CustomerBean</code> object that corresponds to a particular row in
the CUSTOMERS table), and are created or removed from the server's memory
as needed.
Entity Enterprise JavaBeans are also used for this purpose in large scale
applications.
</p>
</section>
<section name="2.5 Business Logic Beans" href="business_logic">
<p>
You should encapsulate the functional logic of your application as
method calls on JavaBeans designed for this purpose.
These methods may be part of the same classes used for the system state
beans, or they may be in separate classes dedicated to performing the
logic.
In the latter case, you will usually need to pass the system state beans
to be manipulated to these methods as arguments.
</p>
<p>
For maximum code re-use, business logic beans should be designed and
implemented so that they do <strong>not</strong> know they are being executed in a
web application environment.
If you find yourself having to import a <code>javax.servlet.*</code> class
in your bean, you are tying this business logic to the web application
environment.
Consider rearranging things so that your <code>Action</code> classes (part
of the Controller role, as described below) translate all required
information from the HTTP request being processed into property setter
calls on your business logic beans, after which a call to an
<code>execute</code> method can be made.
Such a business logic class can be reused in environments other than the
web application for which they were initially constructed.
</p>
<p>
Depending on the complexity and scope of your application, business logic
beans might be ordinary JavaBeans that interact with system state beans
passed as arguments, or ordinary JavaBeans that access a database using
JDBC calls.
For larger applications, these beans will often be stateful or stateless
Enterprise JavaBeans (EJBs) instead.
</p>
<p>
For more about using a database with your application, see the
<a href="../faqs/database.html">Accessing a Database HowTo</a>.
</p>
</section>
<section>
<p class="right">
Next: <a href="building_view.html">Building View Components</a>
</p>
</section>
</body>
</document>