Struts (struts.apache.org/) is an open-source project hosted by the Apache Software Foundation (ASF), which provides a framework for building Web applications. The prime architect, Craig R. McClanahan, based Struts on the "Model 2" architecture, in which Servlets are responsible for the "flow" and data access of the Web application and JavaServer Pages handle the visual presentation. This is basically a variation of the Model-View-Controller (MVC) pattern, in which Struts provides the Controller via an ActionServlet and supporting classes. Working in conjunction with a developer-provided XML file, struts-config.xml, the ActionServlet is responsible for packaging and routing HTTP traffic to appropriate handlers. A developer-provided class extending the Struts Action class provides access to the business logic.
The Struts framework focuses primarily on the controller portion of the MVC pattern, along with some useful view components. The model portion with the business logic is pretty much outside the Struts domain and is accessed through traditional Java techniques, such as Java beans and the Data Access Object (DAO) design pattern.
As a topic, Struts is worthy of an entire book, so only a few of the most commonly-used aspects of the framework will be introduced here.
Overview
Configuration Files
Form Validation
struts-config.xml
Declarative Form Validation
Tiles
In general, when a resource is requested from the client for a Struts Web application, the resource URL will specify logical name rather than, say, a JSP. All requests are handled by the ActionServlet. The ActionServlet looks up the logical resource name in the struts-config.xml file, where that name is mapped to a corresponding Action class that you provide. The Action class execute() method accesses the desired business logic, and then returns an ActionForward instance back to the ActionServlet to tell it what to do next. Usually this ActionForward will be obtained through another logical name mapped in the struts-config.xml file to a "view" component, such as a JSP, to render the results of the request. Or, the action class might decide that the request should be forwarded to another servlet for processing, again through a logical name given in the configuration file. Having the ActionServlet delegate indirectly through the struts-config.xml file makes it relatively easy to change the flow of the Web application as it evolves.
Struts provides a uniform way of handling HTTP form submission and validation by using an ActionForm. You can extend the abstract ActionForm class to perform validation of form input. Struts also supports declarative validation, in which the validating class instance is constructed by Struts, based on declarations in the struts-config.xml file and validation rules defined in the validation.xml file.
The View component of the framework is supported by a set of tag libraries:
Tag Library Descriptor (TLD) URI | Prefix | Description |
---|---|---|
http://jakarta.apache.org/struts/tags-bean |
bean | Java bean access and creation |
http://jakarta.apache.org/struts/tags-html |
html | HTML Form creation |
http://jakarta.apache.org/struts/tags-logic |
logic | Flow control |
http://jakarta.apache.org/struts/tags-nested |
nested | Nested tags in the body of other Struts tags |
http://jakarta.apache.org/struts/tags-template |
template | Dynamic JSP templates |
ttp://jakarta.apache.org/struts/tags-tiles |
tiles | Define the layout of a JSP |
Of these tag libraries, the html
, bean
and logic
libraries are most frequently used, and the nested
and template
libraries are seldom needed. The tiles
library is useful for configuring
a consistent and flexible appearance to pages throughout an application. There is some
overlap in functionality between the Struts bean
and logic
libraries and the JSTL libraries. In cases where either technology could be used,
you might prefer to use the JSTL since it is likely to become part of the JSP 2.0 standard.
In the webAF new project wizard, selecting Struts Framework Web Application as the template will include the necessary Struts "boilerplate" files and tag libraries:
The webAF palette will provide Drag and Drop support for the tag libraries listed above when you choose the Struts template option.
These are the files that are added or modified by webAF when you select the Struts template:
File | In Project? | Description |
---|---|---|
ProjectPath\webapp\WEB-INF\struts-config.xml |
Yes | Main Struts configuration file |
ProjectPath\webapp\WEB-INF\web.xml |
Yes | Deployment descriptor with standard Struts Action servlet and mappings |
ProjectPath\webapp\WEB-INF\validation.xml |
No | Declarative form validation |
ProjectPath\webapp\WEB-INF\validator-rules.xml |
No | Form validation rules |
ProjectPath\webapp\WEB-INF\tiles-defs.xml |
No | Tiles definitions |
ProjectPath\webapp\WEB-INF\classes\resources\application.properties |
Yes | Message resource bundle |
To avoid an unnecessary initial clutter of editor frames, webAF does not include all these files in the project even though they exist. Those with a No in the In Project? column above are less frequently needed and are not initially displayed in the webAF files list. If you need to edit one of these files, just select Insert File Into Project and navigate to the desired file.
When you choose a Struts Web application template, the familiar deployment descriptor will contain the standard Struts action servlet declaration and action mappings, for example:
<!-- Standard Action Servlet Configuration (with debugging) --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> ... <!-- Standard Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
The important thing to note here is that every request for a URL ending with a .do extension (the standard Struts extension) will be processed by the Struts ActionServlet. Though this class can be extended, for many applications this is not necessary and it is used "as-is". The ActionServlet will use information in the struts-config.xml file to decide which Action class will be called upon to actually execute the request for the specified resource.
To illustrate basic Struts processing, suppose you wanted to create a Struts-based Web application with an initial JavaServer Page that has a form to search for studies (documents) on a certain topic, with a pull-down list of possible sources for the studies. When the form is submitted, if any documents from the specified source match the topic, then a page will list the studies found. The steps to accomplish this (given in more detail later) are:
findstudy.jsp
page, using Struts HTML tags to define the form.FindStudyForm.java
class that extends ActionForm
, to hold the request
parameter values and validate them.FindStudyAction.java
class that extends Action
, to check the
submitted topic and source against the database.application.properties
file to add error messages.index.jsp
page to reach the findstudy.jsp
page.found.jsp
file that will be displayed after a successful search, using
Struts logic
and iterate
tags to display the results.struts-config.xml
file to define the global forward,
declare FindStudyForm
as a form bean, and to add the action mappings for:
findstudy.jsp
page initially to display the form.FindStudyForm.java
.findstudy.jsp
with error messages if validation fails.found.jsp
page if the search was successful.Note: For simplicity, the "business logic" is simulated internally in
FindStudyAction.java
for this example. In an actual application, it would be
external.
The Struts HTML tags are preferred over ordinary HTML form tags, because they
are tightly integrated with the Struts framework. This is the code for findstudy.jsp
:
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <html><head><title>Our Web Application - Locate Study</title></head> <body> <h1>Our Web Application</h1> <p><font color="red"><html:errors /></font> <h3>Locate a Study</h3> <table> <html:form action="findstudy" focus="topic"> <tr><td>Topic:</td><td><html:text property="topic"/></td></tr> <tr><td>Source:</td> <td><html:select property="source" > <html:options property="sources"/> </html:select></td></tr> <tr><td><html:submit value="Go" /></tr> </html:form> </table> </body> </html>
The html:errors tag will display errors after validation (described later). When initially displaying the form, it will do nothing.
The action attribute on the form specifies a logical name for the
action that should take place when the button is pushed to submit the form.
The findstudy
name will be mapped to our form validation Java class by
an entry in struts-config.xml
.
When a form is submitted, Struts will instantiate a form bean
extending the ActionForm class, which will encapsulate the form request parameters and perform validation.
Struts will call each setter method that corresponds to the name of a request parameter,
and will then call the validate() method. This method is expected to return an
ActionErrors instance, which encapsulates a collection of error keys. Each
error key will later be used to retrieve a corresponding error message from the
application.properties
file.
package app; import org.apache.struts.action.*; import javax.servlet.http.HttpServletRequest; public class FindStudyForm extends ActionForm { private String topic; private String source; // Simulated sources - replace with actual external bean for business logic: private static String[] sources = { "- Please choose a source -", "Duke Medical Center", "Johns Hopkins Hospital" }; public String getTopic() {return topic; } public void setTopic(String topic) {this.topic = topic; } public String getSource() {return source; } public void setSource(String source) {this.source = source; } public String[] getSources() {return sources; } public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); ActionError newError = null; if (getTopic() == null || getTopic().length() < 1) errors.add("topic", new ActionError("errors.required", "Topic")); if (getSource() == null || getSource().length() < 1 || getSource().startsWith("- ")) errors.add("source", new ActionError("errors.required", "Source")); return errors; } }
Here, the errors.required key is used to retrieve the desired error message from the application.properties file, which is described later.
After the form bean is validated to ensure that values for
both fields were supplied, Struts will instantiate a class extending
Action
to perform the business logic. The execute()
method should be overridden, and returns an ActionForward
to indicate what Struts should invoke next. In the example,
this class will simulate searching the selected source for documents
on the given topic. If any are found, the method will save the collection
of matches in a scoped attribute named results
, and will look up
and return the ActionMapping
for
the logical name success
. If the selected source is not found,
the method will return the ActionMapping
corresponding to logical name failure
. These logical names
will be defined for the action in struts-config.xml
later.
package app; import org.apache.struts.action.*; import javax.servlet.http.*; import java.io.*; public class FindStudyAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res) throws Exception { FindStudyForm findStudyForm = (FindStudyForm) form; ActionErrors errors = new ActionErrors(); ActionError newError = null; String topic = findStudyForm.getTopic(); String source = findStudyForm.getSource(); // Simulated 'search' - replace with actual external bean with business logic: if (topic.equals("Cancer") && source.equals("Duke Medical Center")) { String[] results = new String[] { "'Non-traditional Treatement of Leukemia', 1977", "'Relation of Smoking and Ovarian Cancer', 1982" }; req.setAttribute("results", results); return mapping.findForward("success"); } newError = new ActionError("errors.not.found"); errors.add(ActionErrors.GLOBAL_ERROR, newError); saveErrors(req, errors); return mapping.findForward("failure"); } }
For this example, only the combination of topic="Cancer" and
source="Duke Medical Center" will be recognized
as a match, but in a real application you would replace this with
an external database query. If no match is found for the topic and source,
then a new ActionError
is constructed using the key errors.not.found
to extract the desired message text from the application.properties
file. This
error is added to the errors collection and saved for later display when findstudy.jsp
is
re-executed.
The application.properties
file that is generated by webAF will have lines defining
default standard messages. You can add additional key=value lines as needed.
For this example, one line needs to be added, so the resulting file looks like this:
# -- standard errors -- errors.header=<UL> errors.prefix=<LI> errors.suffix=</LI> errors.footer=</UL> # -- validator -- errors.required={0} is required. errors.byte={0} must be an byte. errors.date={0} is not a date. errors.double={0} must be an double. errors.float={0} must be an float. errors.integer={0} must be an integer. errors.long={0} must be an long. errors.short={0} must be an short. errors.creditcard={0} is not a valid credit card number. errors.email={0} is an invalid e-mail address. # -- other -- errors.cancel=Operation cancelled. errors.detail={0} errors.general=The process did not complete. Details should follow. errors.token=Request could not be completed. Operation is not in sequence. # -- application-specific messages -- errors.not.found=Sorry, no study was found for this topic and source.<br> <i>Hint: Try 'Cancer' and 'Duke Medical Center'</i>
Note: The last two lines shown above are actually a single line.
Here the two keys that are actually used in the application are
errors.required
(used by FindStudyForm.java
) and
errors.not.found
(used by FindStudyAction.java
).
The {0}
parameter will be replaced by the optional argument passed in
to the ActionError
constructor.
For this example you would really like to have the initial entry
point to the Web application, index.jsp
, contain the form.
However, this will not work because the welcome-file
defined in
web.xml
cannot be set up to use a Struts action. This problem
is solved by having index.jsp
forward to the
Struts action corresponding to the findstudy.jsp
page:
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <html><body> <logic:forward name="start"/> </body></html>
Here start
is a logical name that will be mapped to findstudy.jsp
in the struts-config.xml
file.
After the form fields have been validated and one or more matches
has been found for the topic and source, control will be transferred to
a JSP serving as the view component for our action. In our example, this will be a
found.jsp
file that displays a list of documents matching our search criteria:
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <html><head><title>Our Web Application - Studies Found</title></head> <body> <h3>Results Found:</h3> <ol> <logic:iterate id="item" name="results"> <li><bean:write name="item"/></li> </logic:iterate> </ol> </body></html>
Here the Struts logic:iterate
tag will loop throught the collection
stored in the scoped attribute results
, successively assinging each
item in the collection to the item
scripting variable for display
by the bean:write
tag.
The struts-config.xml file is the "glue" that binds the components of a Struts-based application together. Its DTD (Document Type Definition) defines a variety of elements. For this example Web application, changes will be needed in these main areas:
forward
element under the global-forwards
section
to define the target for the logical name specified in the index.jsp
file.form-bean
element under the form-beans
section to define the FindStudyForm
.action
elements under the action-mappings
section
to associate the logical names with the actual action classes and to specify any
additional attributes needed.The index.jsp
file contains a forward to start
.
You need to map this logical resource name to a Struts action,
by adding the line in bold below to the struts-config.xml
file:
<global-forwards> ... <forward name="start" path="viewfindstudy.do" /> </global-forwards>
The viewfindstudy.do
action will be defined later in the file.
You need to assign a logical name for the FindStudyForm
class and
define its type, so Struts will be able to instantiate it. This
is done by adding the line in bold below to the struts-config.xml
file:
</form-beans> ... <form-bean name="findStudyForm" type="app.FindStudyForm" /> </form-beans>
The findStudyForm
name will be used as an attribute value for
an action defined later in the file.
The action
element is perhaps the most important element
in the struts-config.xml
file, and has these attributes:
Attribute | Description |
---|---|
attribute | A Request- or Session-scoped attribute name to use to retrieve the form bean
instance if different from the name attribute value. Optional with no default. |
className | The name of a subclass of org.apache.struts.action.ActionMapping that should be
used to configure this action. Optional, defaulting to
org.apache.struts.action.ActionMapping . |
forward | The application-relative path to a resource that should receive the forwarded
request. Exactly one of the forward, include or type attributes
must be specified. If forward is specified, the Action class will not be instantiated. |
include | The application-relative path to a resource that should serve this
request via an include. Exactly one of the forward, include or type attributes
must be specified. If sinclude is pecified, the Action class will not be instantiated. |
input | The application-relative path to the input form for input validation. Required
if the name attribute is specified. |
name | The logical name of the form-bean associated with this action. Optional with no default. If specified, it must match a previous form-bean element name. |
path | The logical name of the action, specified with a leading slash ("/") character and without the extension (typically .do). Required. |
parameter | A parameter used to pass information to the this Action class instance, which
can be retrieved using the getParameter() method of the ActionMapping passed
as an argument to the execute() method. Optional. |
prefix | A prefix used to match request parameter names to form-bean property names. Optional. |
roles | A comma-delimited list of security role names authorized to perform this action. Optional. |
scope | The scope for the form-bean, either request or session .
Optional, defaulting to session. |
suffix | A suffix used to match request parameter names to form-bean property names. Optional. |
type | A fully-qualified Java class name of a class that extends
org.apache.struts.action.Action . Exactly one of the
forward, include or type attributes must be specified. |
unknown | A flag set to true if this is the default mapping for the application,
which will process requests for URIs not matching any mapping.
Optional and may only be specified true on one mapping in the application. |
validate | A flag set to true if the validate() method for the
form-bean should be called. Optional, defaulting to true . |
For this example, two actions need to be added to the struts-config.xml file:
<action-mappings> ... <action path="/viewfindstudy" parameter="/findstudy.htm" type="org.apache.struts.actions.ForwardAction" name="findStudyForm" input="/findstudy.htm" validate="false" /> <action path="/findstudy" type="app.FindStudyAction" name="findStudyForm" input="/findstudy.htm" validate="true"> <forward name="success" path="found.htm" redirect="false"/> <forward name="failure" path="/findstudy.htm" /> </action> </action-mappings>
The first action defines the viewfindstudy
action, which simply forwards the
request to findstudy.jsp
without validating. This mapping initially
displays the form. The second action defines the findstudy
action, which
calls the validate()
method of the form-bean named findStudyForm
.
If validation fails, control is returned to findstudy.jsp
. If validation
succeeds, then the FindStudyAction
class will be instantiated and its
execute()
method called. The two nested forward
elements
specify the configuration of the ActionFoward
objects that this method
can search for and return. The success
forward will forward the
request to found.jsp
. The failure
forward will
return control to findstudy.jsp
, so the user can try a
different search.
This completes the steps necessary for building the example Struts form validation
application. This is how the application would appear after validation has failed
because the Go
button was pressed without entering any value for
Topic
or Source
:
If validation succeeds and two matching results are found, the found.jsp
page
would look like this:
In the preceding section, a form-bean was implemented by explicitly coding a Java class
extending org.apache.struts.action.ActionForm
. As an alternative, Struts can
automatically create a suitable class to validate form request parameters based on information
that you provide in the validation.xml
file. Here you specify which fields are
required, and typically provide a regular expression defining valid field content.
The DynaActionForm
class provides the implementation. Using declarative validation
can significantly reduce the amount of Java code you have to write for a Web application.
For a description of a complete example using this technique, including the full source code and step-by-step build instructions, see the About the Struts Declarative Validation Example.
As the name suggests, Struts Tiles are rectangular areas of a JSP, typically used to define the layout of a Web site, so that pages will have a consistent look and feel throughout the application. A tile can be constructed from other tiles, so complex layouts are possible.
As a simple example, suppose you want your application to use a classic layout with a header, menu, body and footer region:
|
Each content page of the application will be displayed in the body region
(not to be confused with the HTML <body>
tag - the entire layout
will be rendered between the HTML <body>
and </body>
tags). The header and footer regions will always be the same. The
menu region will show a menu bar, with vertically-arranged links to the "Home",
"Products", "Services", "Mission" and "Contact Us" tile pages.
Clicking link in the menu will display the corresponding content page in the body region.
For simplicity, in the example, body region content pages will only be provided for the
"Home" and "Products" links. Clicking the other links will bring up an
"Under construction" JSP in the body region.
For this example, the layout conceptually illustrated above will be displayed by
a layout.jsp
page. This file will use an HTML table
to define each of the four regions. Inside the <td>
tag
for each region in the table, there will be a Struts tiles tag to render the actual
content. For instance, the body region table cell would contain:
<tiles:insert attribute="body" />
This will render the page specified by the body scoped attribute.
This attribute will have been previously set to the desired basic body-content JSP,
either directly or by a default set in the tiles-config.xml
file.
For example, when a user clicks on the "Products" link in the menu, a
request for tile tiles/products.jsp
will be generated. This file only needs
to contain a few lines:
<tiles:insert definition="layout" flush="true"> <tiles:put name="body" value="/content/productsPage.htm" /> </tiles:insert>
Here the insert
tag first specifies that layout
(a logical name defined in the tiles-defs.xml
file, that in turn maps
to shared/layout.jsp
) should be used for the default layout for this
request. Then the nested tiles:put
tag specifies that the
body
attribute should be set to content/productsPage.jsp
,
which is the file that will render the body region content for this request.
Finally, the end tag will trigger rendering of the entire layout by shared/layout.jsp
,
which will use the scoped attributes to render the correct content for each region.
Thus, each resource associated with a menu item (home page, products, and so on) will actually have a pair of JSP files:
One advantage of this scheme is that you can change the layout without having to make any change at all to the basic content JSP files.
To help distinguish the types of JSP files in our example, the web application will be organized to place the JSP files in three subdirectories:
content
subdirectory for basic content without layout informationtiles
subdirectory for tile JSPs for the body regionshared
subdirectory for the header, footer and menu contentFor our example, these are the tile JSPs and associated basic content JSPs:
Tile | Corresponding basic content | Description |
---|---|---|
tiles/home.jsp |
content/homePage.jsp |
Body region "Home" page |
tiles/products.jsp |
content/productsPage.jsp |
Body region "Products" page |
tiles/unimplemented.jsp |
content/unimplementedPage.jsp |
Body region "Services" page |
Body region "Mission" page | ||
Body region "Contact Us" page |
As mentioned previously, the last three menu items all display the same "stub" JSP for simplicity in the example.
The basic steps to building our Tiles example Web application (given in more detail later) are:
layout.jsp
file to define the overall layout.menu.jsp
file.tiles-defs.xml
file to define the default layout definition.Layout.css
to specify common formatting for the Web application.shared/layout.jsp
FileAn HTML table defines the four regions of the overall layout, where each region's content will be
rendered according to the JSP file specified by the value of the given attribute name.
The tiles:getAsString
tag is used to render the correct title
(which is displayed in the browser's window caption) for the request. The link
tag in the HTML header references the cascading style sheet which will define
the color scheme and font information for the layout of the Web application.
The class
attributes on the various table data (td
) elements specify
which style should be used for each region. The menu region will be 120 pixels wide,
and the body region will use the rest of the available browser width.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <html> <head> <title><tiles:getAsString name="title"/></title> <link rel=stylesheet type="text/css" href="<html:rewrite page='/styles/Layout.css'/>" title="MyStyle"/> </head> <body> <table width="100%"> <tr> <td class="header" colspan="2"><tiles:insert attribute="header" /></td> </tr> <tr> <td class="menu" width="120" valign="top"><tiles:insert attribute="menu" /></td> <td valign="top"><tiles:insert attribute="body" /></td> </tr> <tr> <td class="footer" colspan="2"><tiles:insert attribute="footer" /></td> </tr> </table> </body> </html>
shared/header.jsp
FileFor this example, the header
style will be used to specify a
font color and background color in the style sheet. The company name will be left-aligned and
the slogan right-aligned.
<table width=100%> <tr> <td class="header" ><h2>MyCompany</h2></td> <td class="header" align="right" valign="top"><i>The finest products since 2003</i></td> </tr> </table>
shared/footer.jsp
FileSince the footer has no explicit color information, it will use the
background and font color for the style inherited from the td
element
(in shared/layout.jsp
) that contains it.
The copyright notice will be explicitly centered and italicized. In practice,
this might better be specified in the style sheet too.
<div align="center"> <i>Copyright © 2003, MyCompany</i> </div>
shared/menu.jsp
FileThe following code defines the menu bar, with links to the Home, Products, Services, Mission
and Contact Us tile pages (the last three being unimplemented).
Since we are focusing exclusively on tiles in this example, the links
go directly to the tile JSP files instead of using a logical name to be processed by the
ActionServlet. The Struts html:rewrite
tag takes care of correctly
constructing the URL for the application-relative path to the desired page.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <table > <tr><td class="menu" > <a class="menu" href="<html:rewrite page='/tiles/home.htm'/>">Home</a> </td></tr> <tr><td class="menu" > <a class="menu" href="<html:rewrite page='/tiles/products.htm'/>">Products</a> </td></tr> <tr><td class="menu" > <a class="menu" href="<html:rewrite page='/tiles/unimplemented.htm'/>">Services</a> </td></tr> <tr><td class="menu" > <a class="menu" href="<html:rewrite page='/tiles/unimplemented.htm'/>">Mission</a> </td></tr> <tr><td class="menu" > <a class="menu" href="<html:rewrite page='/tiles/unimplemented.htm'/>">Contact Us</a> </td></tr> </table>
content/homePage.jsp
)Note that this page does not contain any <html>
, <head>
or <body>
tags. These tags should only be present in the
shared/layout.jsp
page, which provides the content for the
overall layout.
<h3>Welcome to MyCompany</h3> At MyCompany, we do lots of good stuff. <p>To find out more, click on one of the menu topics at the left.
content/productsPage.jsp
)This is the JSP file that renders the content listing product information in a table.
It contains no tiles-specific content. A separate Java bean, app.Products.java
provides
access to the business logic, exposing a collection of products through its
getProducts()
method. A helper class, app.Product.java
, in
turn exposes properties for the part number, name, description and price of each product.
For simplicity, the source code for these classes will not be shown.
The Struts logic:iterate
and bean:write
tags handle
the rendering of the table cell contents.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <h3>Products</h3> <table border="2"> <tr> <th>Part No.</th><th>Name</th><th>Description</th><th>Price</th> </tr> <jsp:useBean id="prods" class="app.Products" scope="request" /> <logic:iterate id="theprod" name="prods" property="products"> <tr> <td width="10%"><bean:write name="theprod" property="part" /></td> <td><bean:write name="theprod" property="name" /></td> <td><bean:write filter="false" name="theprod" property="description" /></td> <td align="right">$<bean:write name="theprod" property="price" /></td> </tr> </logic:iterate> </table> <p>We'll have many other great products Real Soon Now.
content/unimplementedPage.jsp
)As discussed previously, this is the "stub" content for the three menu topics that are not actually implemented in this example.
<h3>Under Construction</h3> Sorry, this page has not been implemented yet. Please choose another topic.
tiles/home.jsp
)This JSP file simply inserts the default layout named layout
,
which will be defined in the tiles-config.xml
file.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <tiles:insert definition="layout" flush="true"> </tiles:insert>
tiles/products.jsp
)Here, the JSP inserts the same default layout as was used for the Home page,
but then sets the title
and body
values to meet the needs of the Products page. As a result, the body region will
be rendered by content/productsPage.jsp
instead of the default
JSP.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <tiles:insert definition="layout" flush="true"> <tiles:put name="title" value="MyCompany Products Page" /> <tiles:put name="body" value="/content/productsPage.htm" /> </tiles:insert>
tiles/unimplemented.jsp
)Since requests for menu items Services. Mission and Contact Us
are not implemented for the example, this tile will serve for all three.
The tiles:put
tags replace the default attribute values
with those needed for the stub JSP content page and the corresponding title.
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> <tiles:insert definition="layout" flush="true"> <tiles:put name="title" value="MyCompany Future Page" /> <tiles:put name="body" value="/content/unimplementedPage.htm" /> </tiles:insert>
tiles-defs.xml
File to Define the Default LayoutInsert the existing ...ProjectName\webapp\WEB-INF\tiles-defs.xml
into the project and open it in the webAF editor.
Insert the default definition in the tiles-definitions
element body:
<definition name="layout" path="/shared/layout.htm"> <put name="title" value="MyCompany" /> <put name="header" value="/shared/header.htm" /> <put name="menu" value="/shared/menu.htm" /> <put name="footer" value="/shared/footer.htm" /> <put name="body" value="/content/homePage.htm" /> </definition>
This specifies that the logical tile name layout
will
be handled by the shared/layout.jsp
file. It
then specifies the default title and the four default JSPs for
rendering the respective regions of the tile. These values are the
Home page values.
styles/Layout.css
)This sets the background color for the header and footer to blue, using a white font, and specifies a silver color for the menu region. The title displayed at the top of the body region for each content page will be blue.
td.menu {font-size: 80%; } td.header {background-color: blue; color: white} td.footer {background-color: blue; color: white; font-size:80%} td.menu {background-color: silver} h3 {color: blue}
This completes the steps necessary to build the Struts Tiles example Web application. This is the Home page output in the browser:
This is what appears if you click Products
in the menu tile at the left:
For more information, see the About the Struts Declarative Validation Example.