instead of a , the html browser cannot display the messages even though the tag worked properly by writing out the errors to the response stream. The View Components was the last piece of the puzzle to be sorted out. As it turns out, all the work is performed in the controller part of the framework. The View Tags look for information in the request or session scope and render it as HTML. Now, that is how a view should be – as simple as possible and yet elegant. Struts lets you do that, easy and fast.
2.4 Summary In this chapter you learnt the Struts request lifecycle in quite a bit of detail. You also got a good picture of Struts framework components when we covered the controller and view components. You also got to know relevant sections of struts-config.xml – the Struts configuration file. Armed with this knowledge we will build a Hello World web application using Struts framework in the next chapter.
48
Struts Survival Guide – Basics to Best Practices
Ch a p te r 3 Your first Struts application In this chapter: 1. You will build your first Struts web application step by step 2. You will build a Web ARchive (WAR) and deploy the web application in Tomcat In the last two chapters you have learnt a lot about Struts. In this chapter will take you step by step in building your first Struts application and deploying it onto Tomcat.
3.1 Introduction You can access the sample application by typing http://localhost:8080/App1/index.jsp in the browser. The index.jsp contains a single hyperlink. The link is http://localhost:8080/App1/CustomerDetails.jsp. On clicking the link, CustomerDetails.jsp is displayed. CustomerDetails.jsp contains an HTML Form with two buttons – Submit and Cancel. When the user submits the Form by clicking Submit, Success.jsp is shown if the form validations go through. If the validations fail, the same page is shown back to the user with the errors. If the user clicks Cancel on the form, the index.jsp is shown to the user.
Figure 3.1 The JSP flow diagram for the Hello World Struts application.
Chapter 3. Your First Struts Application
49
Directory Structure overview This is the first time you are building a sample application in this book. Hence we will introduce you to a standard directory structure followed throughout the book when developing applications. Then we will move on to the actual steps involved. Figure 3.2 shows the directory structure. The structure is very logical. The toplevel directory for every sample application is named after the application itself. In this case all the files are located under the directory named App1. The directory src/java beneath App1 contains the Java source files (CustomerForm.java and CustomerAction.java) and also the application’s Message Resource Bundle (App1Messages.properties). Another directory called web-root beneath App1 contains all the JSPs (index.jsp, CustomerDetails.jsp and Success.jsp) and images (banner.gif). The web-root contains a WEB-INF sub directory with files web.xml and struts-config.xml.
Figure 3.2 The directory structure used throughout the book for sample Struts applications.
3.2 Hello World – step by step Here are the steps involved in creating the Struts application. 1. Add relevant entries into the web.xml a. Add ActionServlet Configuration with initialization parameters b. Add ActionServlet Mapping c. Add relevant taglib declaration 2. Start with a blank template for the struts-config.xml. In the struts-config.xml, add the following a. Declare the RequestProcessor b. Create a properties file and declare it as Message Resource Bundle c. Declare the Message Resource Bundle d. Declare the Form-bean
Struts Survival Guide – Basics to Best Practices
50
e. Declare the ActionMapping for the Form-bean f. Add the forwards in the ActionMapping 3. Create the Form-bean class 4. Create the Action class 5. Create the JSP with Struts tags 6. For every tag in the JSP, add key value pairs to the Message Resource Bundle (properties file) created in Step 3b 7. Add Validation in the Form-bean 8. Define the error messages in the Message Resource Bundle 9. Create the rest of the JSPs. Listing 3.1 web.xml for the Struts Application <web-app> Hello World Struts Application <servlet> <servlet-name>action <servlet-class> org.apache.struts.action.ActionServlet <param-name>config <param-value>/WEB-INF/struts-config.xml <param-name>debug <param-value>3 <param-name>detail <param-value>3 1
(continued..)
Chapter 3. Your First Struts Application
51
Listing 3.1 web.xml for the Struts Application (Continued) <servlet-mapping> <servlet-name>action *.do <welcome-file-list> <welcome-file>index.jsp /WEB-INF/struts-html.tld /WEB-INF/struts-html.tld /WEB-INF/struts-bean.tld /WEB-INF/struts-bean.tld
Step 1. As you already know from Chapter 2, the first step in writing a Struts application is to add the ActionServlet entry in web.xml and also map the servlet to the url-pattern *.do. This is shown in Listing 3.1. You already know the meaning of the initialization parameter named config. Here we will introduce two more initialization parameters. They are debug and detail. The debug initialization parameter lets you set the level of detail in the debug log. A lower number means lesser details and a higher number implies detailed logging. It is absolutely essential that you use this logging feature especially in the beginning and also while setting up Struts application for the first time. The debug messages give you enough insight to resolve any configuration related issues. Use them to their fullest capability. In Listing 3.1, we have set the value of debug to 3. The detail initialization parameter lets you set the level of detail in the digester log. Digester is the component that parses the Struts Config file and loads them into Java objects. Some of the errors can be traced by looking at the log created by the Digester as it parses the XML file. Later in this chapter, you will also use two of the Struts Tag libraries to construct the JSP. Hence the relevant tag library definition files – struts-html.tld and struts-bean.tld are also declared in web.xml.
Struts Survival Guide – Basics to Best Practices
52
Another setting of interest in web.xml is the <welcome-file-list>. Typically you would want to type http://localhost:8080/App1 in the browser URL bar and go to index.jsp automatically. This goal is achieved by declaring index.jsp as one of the welcome files.
Step 2. Select a blank template for struts-config.xml and add the following Listing 3.2 struts-config.xml with all entries for App1 <struts-config>
name="CustomerForm" type="mybank.app1.CustomerForm"/>
path="index.jsp"
/>
path="/submitCustomerForm" type="mybank.app1.CustomerAction" name="CustomerForm" scope="request" validate="true" input="CustomerDetails.jsp">
path="Success.jsp"
/>
path="Failure.jsp"
/>
<message-resources parameter="mybank.app1.App1Messages"/>
Step 2a. Declare the controller element in Struts Config file. The element tells the Struts framework to use org.apache.struts.action.RequestProcessor for this application. For
Chapter 3. Your First Struts Application
53
a simple Struts application like App1, this RequestProcessor will suffice. You will use specialized sub classes of RequestProcessor as controllers later in this book. The struts-config.xml is shown in Listing 3.2
Step 2b. Create a properties file under mybank.app1 java package and name it as App1Messages.properties. You will later add key value pairs into this file. Instead of hard coding field names in the JSP, you will use key names from this file to access them. In this way, the actual name can be changed outside the JSP. For now, add the following entry into the Struts Config file. <message-resources parameter="mybank.app1.App1Messages"/>
This is the instruction to the Struts controller to use the App1Message.properties file as the Message Resource Bundle.
Step 2c.Define the form bean by adding a form-bean entry in the form-beans section.
name="CustomerForm" type="mybank.app1.CustomerForm"/>
Step 2d. Define an ActionMapping by adding the following to the actionmappings
path="/submitCustomerForm" type="mybank.app1.CustomerAction" name="CustomerForm" scope="request" validate="true" input="CustomerDetails.jsp">
Step 2e. Add the local forwards to the ActionMapping
path="Success.jsp"
/>
path="Failure.jsp"
/>
At this point, the struts-config.xml looks as shown in Listing 3.3. All entries in bold are added for App1.
Step
3.
Create
the
Form-bean by extending ActionForm in org.apache.struts.action package. Listing 3.3 shows the Form bean. For every field in the HTML Form, there is an instance variable with getter and setter methods in the Form bean. The Struts controller populates the HTML Form by calling the getter methods on the Form bean. When the user submits the HTML
Struts Survival Guide – Basics to Best Practices
54
Form, the Struts controller populates the Form bean with data from HTML Form by calling setter method on the Form bean instance. Step 4. Next, create the Action bean by extending the org.apache.struts.action.Action class. Let us call it CustomerAction. Every class that extends Action implements the execute() method. As you saw earlier in Chapter 2, the RequestProcessor calls the execute() method after populating and validating the ActionForm. In this method you typically implement logic to access middle-tier and return the next page to be displayed to the user. Listing 3.4 shows the execute() method in CustomerAction. In this method, an operation is performed to check is the Cancel button was pressed. If so, the “mainpage” (Global Forward for index.jsp) is shown to the user. The isCancelled() method is defined in the parent Action class. If the operation requested is not Cancel, then the normal flow commences and the user sees Success.jsp. Listing 3.3 CustomerForm – Form Bean for App1 public class CustomerForm extends ActionForm { private String firstName; private String lastName; public CustomerForm() { firstName = “”; lastName = “”; } public String getFirstName() { return firstName; } public void setFirstName(String s) { this.firstName = s; } public String getLastName() { return lastName; } public void setLastName(String s) { this.lastName = s; } }
Step 5. Create the JSP using Struts html and bean tags.
Chapter 3. Your First Struts Application
55
All Struts html tags including the FormTag are defined in struts-html.tld. These tags generate appropriate html at runtime. The TLD file struts-html.tld and struts-bean.tld are declared at the top of JSP and associated with logical names “html” and “bean” respectively. The JSP then uses the tags with the prefix of “html:” and “bean:” instead of the actual tag class name. Listing 3.5 shows the CustomerDetails.jsp. Let us start from the top of this Listing. Listing 3.4 CustomerAction – Action Bean for App1 public class CustomerAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (isCancelled(request)) { System.out.println(Cancel Operation Performed”); return mapping.findForward(“mainpage”); } CustomerForm custForm = (CustomerForm) form; String firstName = custForm.getFirstName(); String lastName = custForm.getLastName(); System.out.println(“Customer First name is “ + firstName); System.out.println(“Customer Last name is “ + lastName); ActionForward forward = mapping.findForward(“success”); return forward; } }
: Under normal circumstances, this JSP tag just generates opening and closing html tags for the page i.e. and . However the real advantage of this tag is when the browser has to render the HTML based on the locale. For instance, when the user’s locale is set to Russia, the tag generates instead of the plain old , so that the browser can attempt to render the Russian characters (if any) in the best possible manner. Setting tells Struts to look for the locale specific resource bundle (More on this later). : As you might be already aware of, one of the best practices in authoring pages is to use relative URLs instead of absolute ones. In order to use relative URLs in HTML, you need to declare the page context root with the declaration tag. All URLs (not starting with “/”) are
Struts Survival Guide – Basics to Best Practices
56
assumed to be relative to the base href. This is exactly what the tag generates.
Listing 3.5 CustomerDetails.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> : :
: The FormTag represented by generates the
HTML representation of the Form as follows: |