The Required XML Descriptors for Your Web App
Even though Ant knows what to do now, your Web application is still not quite ready for deployment yet. You need to add four files to the src/WEB-INF directory: struts-config.xml, tiles-defs.xml, validation.xml, and web.xml. The web.xml descriptor is mandatory for all Web applications. The other three XML descriptors are used by Struts. You should get the four files from the example code archive
: struts-config.xml.v1, tiles-defs.xml.v1, validation.xml.v1, and web.xml.v1. Copy them and rename the copies to struts-config.xml, tiles-defs.xml, validation.xml, and web.xml, respectively. A brief explanation of each file follows.
The struts-config.xml descriptor configures the Struts framework for forms, actions, controllers, messages, and plug-ins. Version one of struts-config.xml is a bare-bones version that just configures the controller, the message resources definition file, the Tiles plug-in, and the Validator plug-in. The controller is the central switchboard: all HTTP requests for Struts actions end up going through it. The message resources definition file stores the text of prompts and errors to make localizing the application easy (i.e., change the content for a different language or country). The Tiles plug-in lets you compose multiple JSPs into a single view for display to the user, similar to what Web portals do. The Validator plug-in lets you do input validation so that you can screen form input for correct values.
The tiles-defs.xml descriptor configures the Tiles plug-in with the pages that the application will output. The file currently has no pages, so it is essentially an empty shell. (For further information on the Tiles plug-in, consult the Struts documentation.)
The validation.xml descriptor configures the Validator plug-in with the types and formats of data that you want to accept for the forms in your application. The file currently has no forms, so it is essentially an empty shell. (For further information on the Validator plug-in, consult the Struts documentation.)
The web.xml descriptor is the standard Web descriptor specified by the J2EE standard. The web.xml descriptor has a well-defined, standard structure. You can find the DTD that describes the structure at java.sun.com/dtd/web-app_2_3.dtd. In version one of the web.xml file supplied in the example code archive, several items are being configured:
- You set the name of the application to "Phone List Application". This name is used for tools that manage WARs and tools that manage running Web applications in a servlet container like Tomcat.
- You define and configure the Struts Action servlet. The definition of the servlet allows us to refer to the Struts Action servlet later in the web.xml descriptor. The configuration turns on or off certain settings and specifies the locations of other Struts configuration files relative to the WAR root directory.
- You map the Action servlet you previously defined so that it handles all URLs that end in ".do".
- You set the session timeout to 720 minutes (half a day) so that you don't have to worry about losing session information because of inactivity (such as lunch breaks). This should be changed to something reasonable like 10 or 30 minutes for a real Web application.
- You set up the welcome file list so that requests for directories behave as if they've had one of the welcome files appended to the directory (e.g., a request for the directory/foo/bar would attempt to retrieve /foo/bar/index.jsp and /foo/bar/index.html first, before displaying a directory listing).
- You define the tag libraries that you use in your application and specify their locations. Tag libraries enable developers to embed tags in JSPs that call code in Java classes, possibly with parameters specified as attributes in the JSP tag or possibly with data contained within the tag. (For more information about tag libraries, consult the JSP tag library specification at java.sun.com/products/jsp/taglibraries.html.)
To build the Web application, change to the ~/projects/phonelist directory, then type "ant". Start up Tomcat, then deploy the application to Tomcat by typing "ant deploy". If all goes well, you should see something similar to Listing 1 in your Tomcat log.
The Tomcat log in a default installation is located at logs/localhost_log.2003-10-08.txt, except that 2003-10-08 is replaced by the actual date. Now run the test by typing "ant test". You should see Listing 2.
The error is an indication that you have not yet set up the code to handle the "/showList.do" URI, which is what the test class requests from the Web server. To fix this problem, you need to write the code that enables the Web application to pass the test. You need to take the following steps:
- Add a section for manageForm in the <form-beans> section of struts-config.xml:
The manageForm form keeps track of contacts that you select on the "show list" page and allows the delete action to retrieve the selections.
- Add sections for "/showList" and "/delete" in the <action-mappings> section of struts-config.xml:
<forward name="success" path="showList"/>
<forward name="success" path="showList"/>
The "/showList" action instantiates the ShowListAction class and executes the code within, making available the "success" forward, which points to a tile called "showList". The ShowListAction presumably forwards to the "success" forward in order to display generated results.
The "/delete" action instantiates the DeleteAction class and executes the code within, making available the "success" forward, which points to a tile called "showList". You do not have to implement the DeleteAction class for the "/delete" action yet. You need to define the "/delete" action right now, because you specify the "/delete" action as the action attribute for the <html:form> tag in showList.jsp. Struts requires that you have at least a definition in struts-config.xml for any forms you use in your JSP pages that are defined with the Struts <html:form> tag.
- Add a section for mainLayout in the <tiles-definitions> section of tiles-defs.xml:
<definition name="mainLayout" path="/mainLayout.jsp">
<put name="titleString" value="Generic Title -- Change Me!" direct="true"/>
<put name="body" value="Generic Content -- Change Me!" direct="true"/>
<put name="bodyParam1" value="" direct="true"/>
The mainLayout definition is a base template that other tile definitions can extend. Specifically, tiles that derive from mainLayout can override the titleString, body, and bodyParam1 tile variables. Child tiles can also introduce new tile variables.
- Add a section for showList in the <tiles-definitions> section of tiles-defs.xml:
<definition name="showList" extends="mainLayout">
<put name="titleString" value="Phone List :: Show List"/>
<put name="body" value="/showList.jsp"/>
The showList tile definition derives from the mainLayout tile definition but has a different titleString value and a different body page.
- Copy ManageForm.java.v1 from the example code archive and put it in src/WEB-INF/classes/com/abcinc/phonelist as ManageForm.java. The ManageForm class is a Struts form class. Struts form classes hold data from forms and let the application retrieve the data in an easy, object-oriented fashion. Struts form classes adhere to the JavaBean standard for accessors and mutators (get and set methods, respectively).
- Copy ShowListAction.java.v1 from the example code archive and put it in src/WEB-INF/classes/com/abcinc/phonelist as ShowListAction.java. The ShowListAction class is a Struts action class. Struts action classes serve as controller classes, which you can think of as switchboards. They direct the flow of control for the application and can sometimes also perform the business logic of the application for small applications where scalability is not a big issue.
As an inelegant but quick hack, sample data was also set up in the ShowListAction class so that you have some data to work with. Ideally you would put the sample data in a separate file outside of the Web application so that the sample data did not get deployed with the application. The sample data population program would simply talk to a database and insert data into a blank or nearly blank database for the application you were building. For simplicity, there is a quick and dirty sample data population method in ShowListAction itself.
- Copy mainLayout.jsp.v1 from the example code archive and put it in src/Web as mainLayout.jsp. The mainLayout.jsp file is the base template for all of the other JSP files in the application. In a larger application, having a base template that all JSP files inherit from will be significantly more useful and will do much to promote consistency and uniformity across all pages of an application.
- Copy showList.jsp.v1 from the example code archive and put it in src/Web as showList.jsp. The showList.jsp file is a particular view for a particular operation. It inherits from mainLayout.jsp. It displays the list of phone contacts. It also contains a form that allows the user to select multiple contacts and then to delete those contacts. The reason the form action is a partial URL ("/delete.do") rather than the full URL (http://localhost:8080/phonelist/delete.do) is that Struts automatically generates the full URL from the context-relative path ("/delete.do"). That is only if you use the Struts <html:form> tag to define the form, however.
- Copy ContactBean.java.v1 from the example code archive and put it in src/WEB-INF/classes/com/abcinc/phonelist as ContactBean.java. The ContactBean class is a simple JavaBean that holds the properties for one contact. It provides a convenient method of storing the information on one contact and for passing such information between pieces of code as a single entity.
- Copy ContactDatabase.java.v1 from the example code archive and put it in src/WEB-INF/classes/com/abcinc/phonelist as ContactDatabase.java. The ContactDatabase class is a simple in-memory storage place for ContactBean instances. ContactDatabase.java rather than a relational database is used to keep this example simple.
- Copy Sequence.java.v1 from the example code archive and put it in src/WEB-INF/classes/com/abcinc/phonelist as Sequence.java. The Sequence class is a simple sequence counter that permits you to generate unique ID values for new ContactBean instances.
After the changes above, the struts-config.xml and tiles-defs.xml descriptors should match up with struts-config.xml.v2 and tiles-defs.xml.v2 from the example code archive. If they do not, you may use the files from the example code archive to continue. The versions of the files from the example code archive contain helpful comments, so use them going forward even if the files you typed up match with the supplied example code fairly well.