logo
header art

Building an Enterprise-Ready Web Application with Struts

June 23, 2005

Building the JSPs

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.

   1 <!-- index.jsp is the standard welcome file; we want to handle welcoming duties
   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.

   01 <%@ page language="java" %>
   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.

   01 <%@ page language="java" %>
   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.