Building an Enterprise-Ready Web Application with Struts
June 23, 2005
Having configured Struts and the webapp to use a number of JSPs, it's time to create those JSPs.
The first JSP on the list is
index.jsp in the root directory of
the webapp; this is the welcome file from
<welcome-file-list> in
web.xml.
2 using a standard ActionForward, so we define index.jsp to redirect to an
3 ActionForward named "welcome" -->
4 <%@ taglib uri="/tags/struts-logic" prefix="logic" %>
5 <logic:redirect forward="welcome">
This is pretty straightforward: the first (non-comment)
line declares the struts-logic tag library so
we can use it, and the second line uses the
<logic:redirect> tag to redirect all
requests to the welcome forward we defined
earlier in struts-config.xml.
Next up, we create the FindRecipe.jsp file in the /WEB-INF/pages/ directory. This JSP is quite a bit more complicated than the last.
02 <%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="html" %>
03 <%@ taglib uri="/WEB-INF/tld/struts-bean.tld" prefix="bean" %>
04 <%@ taglib uri="/WEB-INF/tld/struts-logic.tld" prefix="logic" %>
05 <html:html>
06 <head>
07 <title>
08 <bean:message key="findrecipe.title" />
09 </title>
10 <link href="<html:rewrite page="/example.css" />" rel="stylesheet"
11 type="text/css"></link>
12 </head>
13 <body bgcolor="white">
14 <html:form action="/ShowRecipe.do" focus="name">
15 <table border="0" width="200px">
16 <tr>
17 <th class="right">
18 <bean:message key="prompt.recipename" bundle="fields" />
19 </th>
20 <td class="left">
21 <!-- input field so the user can specify the name of
22 the recipe he or she wishes to see -->
23 <html:text property="name" />
24 <!-- Check to see if there are any messages present
25 related to this propery. If there are, display a list
26 of the messages next to the field. -->
27 <logic:messagesPresent message="true">
28 <ul>
29 <html:messages id="message" property="name" message="true">
30 <li><bean:write name="message" /></li>
31 </html:messages>
32 </ul>
33 </logic:messagesPresent>
34 </td>
35 </tr>
36 <tr>
37 <td colspan="2" align="center"><html:submit /></td>
38 </tr>
39 </table>
40 </html:form>
41 </body>
42 </html:html>
Of special interest are those lines where we use a tag defined in one of the Struts tag libraries. There are several such tags in the JSP, with at least one tag from each of the libraries declared at the top of the file.
First up are tags from the struts-html tag
library; these tags mimic or extend existing HTML tags, such
as the <html:html> tag in line 5. This
tag is a substitute for the standard
<html> tag. The
<html:rewrite> tag on line 10 is used
when you want to write out a link to a resource within the
context of the webapp. Another example of this type of tag
is the <html:form> tag used on line 14.
This tag allows us to bind the form to an underlying
Action so that Action can be
called when the form is submitted. In this case, that
Action is named ShowRecipe.
Recall that we used a servlet-mapping in
web.xml to designate the Struts
ActionServlet, which we called
action, to handle all URIs ending in
.do. The way action does this is
by stripping off the .do and passing it to an
Action with the resulting string as its name
property in struts-config.xml.
The next batch of tags are from the
struts-bean tag library. In this JSP, the only
struts-bean tags we use are the
<bean:message> and
<bean:write> tags. We use the
<bean:message> tag to access messages
from a number of different resources. The first occurrence
of the tag is in <title>, where we use it
to access a message named "findrecipe.title" in the standard
message resource bundle. It is called
resources.application, and it is defined by the
first <message-resources> element defined
in struts-config.xml. The next
occurrence is inside the form, where we use it to access a
message named "prompt.recipename" in the "fields" bundle,
which is defined by the second
<message-resources> element defined in
struts-config.xml. NOTE: The name
of a bundle is just the word following "resources." in the
parameter attribute of the
<message-resources> element that defines
the bundle in struts-config.xml.
Next is the <bean:messages> tag; we use
this tag to loop through any messages available in the
session/request. Then we use id="message" to
specify that we only want the collection of
ActionMessages associated with the key
"message". We use property="name" to filter out
all messages except those associated with the "name"
property. Finally, we use message="true" to
filter out ActionErrors. The last of the
struts-bean tags in this JSP is the
<bean-write> tag. This tag is used to
write out text to the page, much like the
<%= %> construction when using
scriptlets. Here, we use the <bean-write>
tag to write out any error messages associated with the
name property.
The remaining Struts custom tag,
<logic:messagesPresent>, is defined by
the struts-logic tag library. We use it to
determine whether there are messages that should be
displayed to the user. We use
message="true" to include instances of
org.apache.struts.action.ActionMessage
in the check while excluding instances of
org.apache.struts.action.ActionError. Struts
best practices recommend avoiding ActionError,
so using message="true" will simply reinforce
best practices.
The last JSP in our webapp is
ShowRecipe.jsp. This is
the JSP that displays the recipe the user requested
on the FindRecipe.jsp, and
like FindRecipe.jsp, this
JSP is found in the
/WEB-INF/pages/ directory.
From a Struts standpoint, this page is more of the
same stuff we saw on
FindRecipe.jps. However,
it does leverage some JSP functionality we have yet
to examine: the <jsp:useBean>
and <jsp:getProperty> tags.
02 <%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="html" %>
03 <%@ taglib uri="/WEB-INF/tld/struts-bean.tld" prefix="bean" %>
04 <html:html>
05 <jsp:useBean id="recipe" scope="request"
06 class="com.skillfusion.examples.struts.bizobjs.Recipe" />
07 <head>
08 <title>
09 <bean:message key="showrecipe.title" />
10 <jsp:getProperty name="recipe" property="name" />
11 </title>
12 <link href="<html:rewrite page="/example.css" />" rel="stylesheet"
13 type="text/css"></link>
14 </head>
15 <body>
16 <table>
17 <tr>
18 <td class="right">
19 <bean:message key="recipe.name.caption" bundle="fields" />
20 </td>
21 <td class="left">
22 <jsp:getProperty name="recipe" property="name" />
23 </td>
24 </tr>
25 <tr>
26 <td class="right">
27 <bean:message key="recipe.ingredients.caption" bundle="fields" />
28 </td>
29 <td class="left">
30 <jsp:getProperty name="recipe" property="ingredients" />
31 </td>
32 </tr>
33 <tr>
34 <td class="right">
35 <bean:message key="recipe.prepInstructions.caption" bundle="fields" />
36 </td>
37 <td class="left">
38 <jsp:getProperty name="recipe" property="prepInstructions" />
39 </td>
40 </tr>
41 <tr>
42 <td class="right">
43 <bean:message key="recipe.cookInstructions.caption" bundle="fields" />
44 </td>
45 <td class="left">
46 <jsp:getProperty name="recipe" property="cookInstructions" />
47 </td>
48 </tr>
49 <tr>
50 <td class="right">
51 <bean:message key="recipe.misc.caption" bundle="fields" />
52 </td>
53 <td class="left">
54 <jsp:getProperty name="recipe" property="misc" />
55 </td>
56 </tr>
57 </table>
58 </body>
59 </html:html>
On line 5, we use
<jsp:useBean> to pull an instance
of com.skillfusion.examples.struts.bizobjs.Recipe
named "recipe" out of the request. This object was
placed in the request by
ShowRecipeAction, which forwarded to
this JSP. Starting on line 22, we use
<jsp:getProperty> to access and
display the properties of recipe.

