Hello World - step by step


Hello World ‚ step by step

Here are the steps involved in creating the Struts application.

  1. Add relevant entries into the web.xml

    1. Add ActionServlet Configuration with initialization parameters

    2. Add ActionServlet Mapping

    3. Add relevant taglib declaration

  2. Start with a blank template for the struts-config.xml. In the struts-config.xml, add the following

    1. Declare the RequestProcessor

    2. Create a properties file and declare it as Message Resource Bundle

    3. Declare the Message Resource Bundle

    4. Declare the Form-bean

    5. Declare the ActionMapping for the Form-bean

    6. 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 < bean:message > 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.

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 .

Listing 3.1: web.xml for the Struts Application
 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app>   <display-name>Hello World Struts Application</display-name>   <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>3</param-value>     </init-param>       <init-param>       <param-name>detail</param-name>       <param-value>3</param-value>     </init-param>     <load-on-startup>1</load-on-startup>   </servlet>                                            <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern>   </servlet-mapping>   <welcome-file-list>     <welcome-file>index.jsp</welcome-file>   </welcome-file-list>   <taglib>     <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-html.tld</taglib-location>   </taglib>   <taglib>     <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>   </taglib> </web-app> 
 

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 .

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

Step 2a. Declare the controller element in Struts Config file. The < controller > element tells the Struts framework to use org.apache.struts.action.RequestProcessor for this application. For 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

 <controller processorClass=             "org.apache.struts.action.RequestProcessor" /> 
Listing 3.2: struts-config.xml with all entries for App1
 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>   <form-beans>   <  form-bean  name="CustomerForm"   type="mybank.app1.CustomerForm"/  >   </form-beans>   <global-forwards>   <  forward name="mainpage"  path="index.jsp"  /  >   </global-forwards>   <action-mappings>   <  action   path="/submitCustomerForm"   type="mybank.app1.CustomerAction"   name="CustomerForm"   scope="request"   validate="true"   input="CustomerDetails.jsp"  >   <  forward name="success"  path="Success.jsp"  /  >   <  forward name="failure"  path="Failure.jsp"  /  >   <  /action  >   </action-mappings>   <  controller processorClass="org.apache.struts.action.RequestProcessor"/  >   <  message-resources parameter="mybank.app1.App1Messages"/  > </struts-config> 
 

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.

 <form-bean  name="CustomerForm"               type="mybank.app1.CustomerForm"/> 

Step 2d. Define an ActionMapping by adding the following to the action-mappings

 <action   path="/submitCustomerForm"               type="mybank.app1.CustomerAction"               name="CustomerForm"               scope="request"               validate="true"               input="CustomerDetails.jsp">     </action> 

Step 2e. Add the local forwards to the ActionMapping

 <forward name="success"  path="Success.jsp"  />        <forward name="failure"  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.

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 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 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.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;   } } 
 

Step 5. Create the JSP using Struts html and bean tags.

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.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" %> <html:html>   <head>     <html:base/>   </head>   <body>     <html:errors/>     <html:form action="/submitCustomerForm">       <bean:message key="prompt.customer.firstname"/>:       <html:text property="firstName" size="16" maxlength="16"/>       <BR>       <bean:message key="prompt.customer.lastname"/>:       <html:text property="lastName" size="16" maxlength="16"/>       <BR>       <html:submit>         <bean:message key="button.save"/>       </html:submit>       &nbsp;       <html:cancel>         <bean:message key="button.cancel"/>       </html:cancel>     </html:form>   </body> </html:html> 
 

< html:html >: Under normal circumstances, this JSP tag just generates opening and closing html tags for the page i.e. < html > and < /html >. 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 < html lang= ‚½ru ‚½ > instead of the plain old < html >, so that the browser can attempt to render the Russian characters (if any) in the best possible manner. Setting < html:html locale="true" > tells Struts to look for the locale specific resource bundle (More on this later).

< html:base >: 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 < base href= ‚½ ‚ ‚½ > tag. All URLs (not starting with ‚“/ ‚½) are assumed to be relative to the base href . This is exactly what the < html:base/ > tag generates.

< html:form >: The FormTag represented by < html:form > generates the HTML representation of the Form as follows :

 <form name=.. action=.. method=GET>) 

It has one mandatory attribute ‚ action . The action attribute represents the ActionMapping for this form. For instance, the action attribute in Listing 3.5 is /submitCustomerForm . Note that the FormTag converts this into a HTML equivalent as follows:

 <form name=CustomerForm action=/App1/submitCustomerForm.do> 

The corresponding ActionMapping in Struts Config file is associated with CustomerForm . Before displaying the page to the user, the FormTag searches the request scope for an attribute named CustomerForm . In this case, it does not find one and hence it instantiates a new one. All attributes are initialized to zero length string in the constructor. The embedded tags use the attributes of the CustomerForm in the request scope to display their respective values.

< html:text >: The < html:text > tag generates the HTML representation for the text box. It has one mandatory attribute named property . The value of this XML attribute is the name of the JavaBeans property from the Form bean that is being represented. For instance, the < html:text property= ‚½firstname ‚½/ > represents the JavaBeans property firstName from the CustomerForm . The < html:text > tag will get the value of the JavaBeans property as indicated by the property attribute. Since the CustomerForm was newly instantiated , all its fields have a value of zero length string. Hence the < html:text property= ‚½firstName ‚½ / > generates a html textbox tag of < input type= ‚½text ‚½ name= ‚½firstName ‚½ value= ‚½ ‚½ / >. Listing 3.6 shows the generated HTML.

Listing 3.6: Generated HTML for CustomerDetails.jsp
 <html lang="en"> <head>   <base    href="http://localhost:8080/App1/CustomerDetails.jsp" /> </head>   <body>     <form name="CustomerForm"         action="/App1/submitCustomerForm.do">        First Name:        <input type="text" name="firstName" value="" />        <BR>        Last Name:        <input type="text" name="lastName" value="" />        <BR>        <input type="submit" value="Save Me"/>        &nbsp;        <input type="submit"                name="org.apache.struts.taglib.html.CANCEL"                value="Cancel Me">     </form>   <body> </html> 
 

< html:submit >: This tag generates the HTML representation for the Submit button as < input type= ‚½submit ‚½ value= ‚½Save Me ‚½ >.

< html:cancel >: This tag generates the HTML representation for the Cancel button. This must have started a though process in your mind now. Why do I need a < html:cancel > when I already have < html:submit >? Well, this is because of the special meaning of Cancel in everyday form processing. Pressing a Cancel button also results in Form submission. You already know that when validate is set to true, the form submission results in a validation. However it is absurd to validate the form when form processing is cancelled. Struts addresses this problem by assigning a unique name to the Cancel button itself. Accordingly, a JSP tag < html:cancel > Cancel Me < /html:cancel > will generate equivalent HTML as follows:

 <input type="submit"                   name="org.apache.struts.taglib.html.CANCEL"                   value="Cancel Me"> 

Just before the RequestProcessor begins the Form validation, it checks if the button name was org.apache.struts.taglib.html.CANCEL . If so, it abandons the validation and proceeds further. And that ‚ s why < html:cancel > is different from < html:submit >.

< html:errors >: This tag displays the errors from the ActionForm validation method. You already looked at its working in the last chapter.

In the generated html, you might notice that the < html:errors/ > tag did not translate into any meaningful HTML. When the form is displayed for the first time, the validate() method in CustomerForm hasn ‚ t been executed yet and hence there are no errors. Consequently the < html:errors/ > tag does not output HTML response.

There is another tag used in Listing 3.5 called < bean:message > for which we did not provide any explanation yet. The < bean:message > tags in the JSP generate regular text output in the HTML (See Listing 3.6). The < bean:message > tag has one attribute named ‚“ key ‚½. This is the key to the Message Resource Bundle. Using the key, the < bean:message > looks up the properties file for appropriate values. Hence our next task is to add some key value pairs to the properties file created in Step 3b.

Step 6. For every < bean:message > tag in the JSP, add key value pairs to the Message Resource Bundle ( App1Messages.properties ) created in Step 3b. This is pretty straightforward. Listing 3.7 shows the App1Messages.properties . We will add more contents into this file in Step 9. But for now, this is all we have in the Message Resource Bundle.

Listing 3.7: App1Messages.properties
 prompt.customer.firstname=First Name prompt.customer.lastname=Last Name button.save=Save Mes button.cancel=Cancel Me 
 

Step 7. Now that the CustomerForm is displayed to the user, what if user enters wrong data and submits the form? What if the user does not enter any data? These boundary conditions have to be handled as close to the user interface as possible for reasons discussed in Chapter 2. That ‚ s why the validate() method is coded in every Form bean. You have seen the validate() method before in Chapter 2. It is repeated in Listing 3.8.

Listing 3.8: validate() method in CustomerForm
 public ActionErrors validate(ActionMapping mapping,                               HttpServletRequest request) {     ActionErrors errors = new ActionErrors();     if (firstName == null  firstName.trim().equals("")) {         errors.add("firstName",                   new ActionError("error.cust.firstname.null"));     }     return errors; } 
 

According to the business requirements set for this application, first name has to exist all the time. Hence the validate() method checks to see if the first name is null or if the first name is all spaces. If either of this condition is met, then it is an error and according an ActionError object is created and added to the ActionErrors. Think of the ActionErrors as a container for holding individual ActionError objects. In Listing 3.8, the ActionError instance is created by supplying a key ‚“ error.cust.firstname.null ‚½ to the ActionError constructor. This key is used to look up the Message Resource Bundle. In the next step, the keys used for error messages are added to the Message Resource Bundle.

Step 8. In Step 7, validate() method was provided with the error messages identified by keys. In this step, the error message keys are added to the same old App1Messages.properties. The modified App1Messages.properties is shown in Listing 3.9. The new entry is shown in bold. Note that we have used a prefix ‚“ error ‚½ for the error message entries, a prefix of ‚“ button ‚½ for button labels and a prefix of ‚“ prompt ‚½ for regular HTML text. There is no hard and fast rule and it is only a matter of preference. You can name the keys anyway you want.

Listing 3.9: Updated App1Messages.properties
 prompt.customer.firstname=First Name prompt.customer.lastname=Last Name button.save=Save Me button.cancel=Cancel Me  error.cust.firstname.null=First Name is required  
 

Step 9. In the previous steps, you created most of the artifacts needed for the Struts application. There are two more left. They are index.jsp and Success.jsp . These two JSPs are pretty simple and are shown in Listing 3.10 and Listing 3.11 respectively.

Listing 3.10: index.jsp
 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html:html>   <head>     <html:base/>   </head>   <body>     <html:link page="CustomerDetails.jsp">Customer Form</a>   </body> </html:html> 
 
Listing 3.11: Success.jsp
 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html:html>   <head>     <html:base/>   </head>   <body>     <h1>My First Struts Applications is a Success.</h1>   </body> </html:html> 
 

Here we are introducing a new tag ‚ < html:link >. This generates a hyperlink in the HTML. You must be wondering why would you need another tag when < a href= ‚½ ‚ ‚½ > might as well do the job. There are many advantages of using the < html:link > tag. We will explain one advantage relevant to our discussion ‚ URL rewriting. We will look at other uses of the < html:link > tag in Chapter 4.

Since HTTP is stateless, J2EE web applications maintain data in a special object called HTTPSession . A key on the server side uniquely identifies every user ‚ s HTTPSession . You can think as if the Servlet container is storing all the active sessions in a big Hash Map. A per-session cookie is created when the user accesses the web application for the first time. There after the browser sends the per-session cookie to the server for every hit. The cookie serves as the key into the Servlet container ‚ s global Hash Map to retrieve the user ‚ s HTTPSession .

Under normal circumstances this works fine. But when the user has disabled cookies, the Servlet container uses a mechanism called URL rewriting as a work around. In URL rewriting, the Servlet container encodes the per-session cookie information into the URL itself. However the container does not do this unless you ask it to do so explicitly. You should make this provision to support users with cookie-disabled browsers since you can never anticipate the user behavior in advance. Therefore, when using the regular < a href= ‚½ ‚ ‚½ > for the hyperlinks , you have to manually encode the URL by using the API HttpServletResponse.encodeURL() method to maintain the session as follows:

 <a href=<%= response.encodeURL(CustomerDetails.jsp) %> >           Customer Form</a> 

Now, that ‚ s a painful and laborious thing to do for every link in your application. In addition, you are unnecessarily introducing a scriptlet for every encoding. The good news is that the < html:link > does that automatically. For instance,

 <html:link page=CustomerDetails.jsp>Customer Form</a> 

generates a HTML as follows by rewriting the URL by including the jsessionid .

 <a  href=http://localhost:7001/App1/CustomerDetails.jsp;jsessionid=1 Os1Ame91Z5XCe3l648VNohduUlhA69urqOL1C2mT1EXzsQyw2Ex!-824689399>Customer Form</a> 



Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net