Section 8.1. Struts-Layout


8.1. Struts-Layout

Struts-Layout (http://struts.application-servers.com) is a custom tag library that provides a number of ready-made Struts components. The most notable for our purposes is the suggestion field. Although Struts-Layout has other tags (for panels, input fields, tables, treeviews, sortable lists, data grids, pop-ups, calendars, and more), the suggestion field is the only one that's Ajax-enabled, and it's such a nice implementation that it's worth discussing. The other tags in the Struts-Layout library are worth investigating, too, but I'll leave that up to you. Its creators claim that Struts-Layout enables you to create web pages without knowing HTML. That's a bit extreme, but they have done a good job of encapsulating powerful features into a tag library.

Figure 8-1 shows a simple application that uses the Struts-Layout suggestion field. It's easy to see the power of the Struts-Layout tags even in this simple example. The view is created with only four Struts-Layout tags: <layout:html>, <layout:form>, <layout:suggest>, and <layout:submit> (more about these tags later). You don't need to write any JavaScript to create a suggestion field, and only minimal HTML is required.

Figure 8-1. A Struts-Layout suggestion field


Most of the work involved in getting a Struts-Layout application running is in the configuration. Setting up the application to run on the server can take a little work, so let's step through it now.

8.1.1. Installing Struts-Layout

First, you'll need to download and install the Struts-Layout library. Download the library from http://struts.application-servers.com/download.html. After unpacking the .zip file, locate the tag library struts-layout.tld and the .jar file struts-layout.jar; you'll find these in the directory src/library. You'll also need numerous support files, which are located in the /resources directory. For the current release of Struts-Layout, move the images in /resources/images into /resources/config. Then copy that entire config directory into the root of your web application. Put struts-layout.jar in your application's WEB-INF/lib directory, and put struts-layout.tld in WEB-INF. Figure 8-2 shows how your development environment and WAR file should be organized.

Figure 8-2. The Struts-Layout directories and files


A lot of support files need to be in the right place before Struts-Layout will work properly, so if you have trouble, refer to this diagram. The version of Struts-Layout (version 1.2) that I used for this application did not have all the files in the correct directories, and I had to move some files around to get it to work.

8.1.2. Writing the Struts-Layout JSP

It's simply amazing how such a small bit of code in the JSP can create a suggestion field for an application.

The JSP begins with a <taglib> directive (Example 8-1). This directive specifies the location of the tag library (/WEB-INF/struts-layout.tld) and assigns the layout prefix to the tags defined in the struts-layout.tld file. (I've used the prefix layout to stay consistent with the suggested use of the tag library, but the prefix is arbitrary; you can use anything, provided it isn't used elsewhere in your application, although it's a good idea to stick with a prefix that's related to the library's purpose.)

Example 8-1. usermanager.jsp created with Struts-Layout tags

 <%@ taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %> <link href="default.css" media="screen" rel="Stylesheet" type="text/css" /> <layout:html>     <layout:form action="useraction.do" style key="Suggest Test">         <layout:suggest name="username" suggestAction="/getSuggestionList"                         property="username" key="Username" style                         value="" suggestCount="8" />         <layout:submit />     </layout:form> </layout:html> 

Early in the JSP, we link to default.css, a stylesheet provided by Struts-Layout that gives us the colors and alignment that we need to create the suggestion field.

<layout:html> defines the HTML area that will be displayed. When using Struts-Layout, avoid using any HTML in the JSP. Don't substitute an <HTML> tag for <layout:html>the <layout:html> and <HTML> tags are not equivalent.

Next, the <layout:form> tag sets up the form and the Struts action to which the form submits. This line also defines which CSS class the form will use, as well as the title that is displayed on top of the select box (known as the key). Figure 8-1 shows how the key is displayed. The action that the <layout:form> sets is useraction.do; we'll define this action in the later section "The Struts Configuration."

The <layout:suggest> tag declares the Ajax-enabled suggestion field. It's a complicated tag, with a number of parameters:


name

Specifies the bean used to get the suggestion field's properties; in this case, the "username" bean. The bean must be in the current scope (pageContext, request, session, or application scope).


suggestAction

Must match the path for the web service that returns the list of data for the suggestion field. Its value, "/getSuggestionList", is defined in struts-config.xml (see Example 8-5).


property

Defines the name of the parameter that the form passes to the Struts action. The form in our case is UserForm.java (Example 8-3); it contains the property username, which must match the property parameter in the <layout:suggest> tag.


key

Specifies the label that will be displayed for the field; this label ("Username") is visible in Figure 8-1.


styleId

Sets up the CSS style for the suggestion field. If you use the styleId attribute, you need to include a Cascading Style Sheet and set up a style that matches the styleId in the <layout:suggest> tag.


value

Sets the suggestion field's initial value. We want to start out with the field empty, so the value for this attribute is the empty string (""). The value parameter is required, so we cannot omit it. If you put a string in the value field, you will see that string when the form comes up.


suggestCount

Specifies the maximum number of suggestions that are displayed at any given time. In our case, the maximum is eight. If there are more than eight matches, a scrollbar appears to allow the user to scroll through the matches.

There are many fields in the <layout:suggest> definition that are not listed in the Struts-Layout documentation, and some of these are critical. If you find that you need more information about any tag in Struts-Layout, open the struts-layout.tld file in a text editor and search for the name of the tag you're interested in (for example, the suggest tag); all the attributes of that tag are wrapped in <attribute> tags. Since Ajax is relatively new, you should expect libraries like Struts-Layout to change, and you'll frequently find that the documentation isn't up-to-date. When you're in this situation, always check the .tld file: that will give you the clues you need.


That's it for the tags! They are very compact and deceptively powerful; just one tag, <layout:suggest>, encapsulates all of the client functionality that required many lines when we coded it by hand in Chapter 5.

Name this JSP usermanager.jsp and copy it into the root of your web application context (the war directory).

Now it's time to do some configuration in web.xml. The Struts package (struts.jar) includes a special servlet called the ActionServlet. This servlet reads a configuration file; the name of this configuration file is specified as the config parameter in web.xml. In most cases, the name of the configuration file should be /WEB-INF/struts-config.xml. The web.xml file showing the setup for Struts and the Struts-Layout tag file is presented in Example 8-2.

Example 8-2. web.xml

 <web-app>     <servlet>         <servlet-name>action</servlet-name>         <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>         <init-param>             <param-name>application</param-name>             <param-value>ApplicationResources</param-value>         </init-param>         <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>     <!-- Action Servlet Mapping -->     <servlet-mapping>         <servlet-name>action</servlet-name>         <url-pattern>*.do</url-pattern>     </servlet-mapping>     <!-- The Welcome File List -->     <welcome-file-list>         <welcome-file>usermanager.jsp</welcome-file>     </welcome-file-list>     <!-- taglibs -->     <taglib>         <taglib-uri>/WEB-INF/struts-layout.tld</taglib-uri>         <taglib-location>/WEB-INF/struts-layout.tld</taglib-location>     </taglib> </web-app> 

This is a fairly typical web.xml file for a Struts application. It configures a single servlet, the Struts ActionServlet, and specifies the location of struts-layout.tld. It also sets the name of the Struts configuration file, struts-config.xml. This file controls which Struts actions the Struts application will use.

The last piece of configuration in web.xml is the setup of the Struts-Layout tag library. That's handled by the <taglib> tag toward the end of the file; it defines the layout tags that are used in the JSPs.

Later, you'll see how struts-config.xml sets the actions, forms, and tiles (views) to set up the Struts application.

8.1.3. Struts Action Forms

A typical JSP application connects a JSP to a servlet through a call to HTTPGet( ) or HTTPPost( ). Then the servlet gets any information it needs through a call to the request object (usually via request.getParameter("paramname")).

Struts introduces the concept of an action form to make a cleaner interface between the client and the server, avoiding all the request.getParameter( ) calls on the server. An action form is a Struts class that encapsulates the parameters passed from the client to the server. The form you use in your application extends the org.apache.struts.action.ActionForm class, and each parameter that you post to the server is represented in the action form.

An action form is a Java bean that stores data for the view. Basically, that means that the form has private properties and public getter and setter methods for each property.

The data in the form is set by actions that are invoked before the JSP uses it. The JSP typically populates itself by calling tag libraries with the property field set to the field name of the form. For example, to access the lastName property of the form, a JSP could include the <layout:write> tag and pass the property field with the property="lastName" attribute. Look at results.jsp to see the exact syntax used to get the lastName.

So, instead of calling request.getParameter("paramname"), you can get the form from the action by calling UserForm userForm = (UserForm)form. The form is passed into the ActionServlet, so all you have to do is cast it to the UserForm class. At this point you can get the parameters from the form by using a get method: String username = userForm.getUsername( ).

Example 8-3 presents the UserForm that stores the data for the view, with its getters and setters: it's a plain old Java bean with accessor methods for username, firstName, and lastName.

Example 8-3. The UserForm

 public class UserForm extends ActionForm {     private String username;     private String firstName;     private String lastName;     public String getFirstName( ) {         return firstName;     }     public void setFirstName(String firstName) {         this.firstName = firstName;     }     public String getLastName( ) {         return lastName;     }     public void setLastName(String lastName) {         this.lastName = lastName;     }     public String getUsername( ) {         return username;     }     public void setUsername(String username) {         this.username = username;     }     public void reset(ActionMapping mapping, HttpServletRequest request) {         this.username = "";         this.lastName = "";         this.firstName = "";     } } 

8.1.4. What's an Action, and What Happened to My Servlet?

The familiar Java servlet is now represented by a Struts action. When writing Struts applications, instead of writing servlets, you write actions. Think of servlets as having been deprecated in favor of the Struts Action class. The UserAction class extends the Struts Action class, and instead of putting redirection code in the servlet, the program flow is controlled by struts-config.xml. The Struts action connects the business logic to the view.

Example 8-4 shows the code for the UserAction. Notice how the execute( ) method gets the UserForm, reads the username from the UserForm, calls a private method to gather information from the database, and then sets other values in the UserForm to be passed on to the next part of the application. The next part of the application is accessed by the call to mapping.findForward("success"), which forwards the user to the "success" tile. That tile is defined as results.jsp in the struts-config.xml file, which we'll look at in the next section.

Example 8-4. The Struts action, UserAction.java

 public class UserAction extends Action {     public ActionForward execute(ActionMapping mapping,             ActionForm form,             HttpServletRequest request,             HttpServletResponse response) {         String username = ((UserForm)form).getUsername( );         HashMap userInfoMap = getUserInfo(username);         String firstName =(String)userInfoMap.get("firstName");         String lastName =(String)userInfoMap.get("lastName");         ((UserForm)form).setFirstName(firstName);         ((UserForm)form).setLastName(lastName);         return mapping.findForward("success");     }     private HashMap getUserInfo(String username) {         HashMap hashMap = null;         Connection con = DatabaseConnector.getConnection( );         try {             Statement statement = con.createStatement( );             String sqlString = "select FIRST_NAME,LAST_NAME from USERS where                     USERNAME='"+username+"';";             ResultSet resultSet = statement.executeQuery(sqlString);             if (resultSet.next( )) {                 hashMap = new HashMap( );                 hashMap.put("firstName",resultSet.getString(1));                 hashMap.put("lastName",resultSet.getString(2));             }         }         catch (Exception e) {             System.out.println("exception caught getting usernames");         }         finally {             if (con != null) {                 try {                     con.close( );                 }                 catch (SQLException e) {                 }             }         }         return hashMap;     } } 

8.1.5. The Struts Configuration

Now, on to the struts-config.xml file. Struts is an implementation of an MVC framework, where the model (the application data) is represented by your own objects (typically Java beans), the view is implemented by JSPs, and the actions, as configured by struts-config.xml, form the controller. The Struts Form objects carry information between the Views and the Actions. Tile is Struts lingo for the view, which is usually an HTML or JSP page.

The Struts configuration file, struts-config.xml, is presented in Example 8-5.

Example 8-5. struts-config.xml

 <?xml version="1.0" encoding="UTF-8"?> <!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>     <data-sources />     <form-beans>         <form-bean name="userForm"                    type="com.oreilly.ajax.UserForm" />     </form-beans>     <global-exceptions />     <global-forwards />     <action-mappings>         <action path="/useraction"                 type="com.oreilly.ajax.UserAction"                 name="userForm"                 input="/usermanager.jsp">             <forward name="success" path = "/results.jsp" />             <forward name="failure" path="/usermanager.jsp" />         </action>         <action path="/getSuggestionList"                 type="com.oreilly.ajax.UsernameSuggestAction">         </action>     </action-mappings>     <controller bufferSize="4096" debug="0" />     <message-resources parameter="com.oreilly.ApplicationResources" /> </struts-config> 

The <form-beans> tag tells the Struts application that when userForm is referenced, it should satisfy that reference with an instance of com.oreilly.ajax.UserForm (the Struts form that we developed earlier). userForm is nothing more than an alias for com.oreilly.ajax.UserForm.

userForm is referenced in results.jsp (Example 8-6), which displays information about the selected item. When a user is selected from the suggestion field in usermanager.jsp, control is passed to the UserName action and information about the selected user is stored in the UserForm. Next, control passes to results.jsp, which displays the results stored in the UserForm to the user.

Example 8-6. results.jsp

 <%@ taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %> <link href="default.css" media="screen" rel="Stylesheet" type="text/css" /> <layout:html> Results:     <layout:row>         <layout:column>             Username         </layout:column>         <layout:column>             <layout:write name="userForm" property="username" />         </layout:column>    </layout:row>    <layout:row>         <layout:column>             First Name:         </layout:column>         <layout:column>             <layout:write name="userForm" property="firstName" />         </layout:column>    </layout:row>    <layout:row>         <layout:column>             Last Name:         </layout:column>         <layout:column>             <layout:write name="userForm" property="lastName" />         </layout:column>    </layout:row> </layout:html> 

The JSP retrieves the userForm with the <layout:write> tag. Once again, this JSP doesn't require any HTML; the Struts-Layout tag library takes care of all that for us. You can mix HTML tags with the layout: tags to give you more control over the page's appearance, but don't forget about the CSS file if you want more control over the look of the page.

Figure 8-3 shows the results page displaying information about the selected user.

Figure 8-3. The results JSP


8.1.6. Where Does the Data Come From?

The data behind this application comes from the MySQL database that we have been using throughout this book. The application uses the USERS table in the AJAX database we created in Chapter 5. It also uses the DatabaseConnector class from Chapter 5 (see Example 8-7).

Example 8-7. The DatabaseConnector class

 package com.oreilly.ajax; import java.sql.Connection; import java.sql.DriverManager; public class DatabaseConnector {     public static Connection getConnection( ) {         Connection con = null;         String driver = "com.mysql.jdbc.Driver";         try {             Class.forName(driver).newInstance( );         } catch (Exception e) {             System.out.println("Failed to load mySQL driver.");             return null;         }         try {             con = DriverManagergetConnection(                     "jdbc:mysql:///AJAX?user=ajax&password=polygon");         } catch (Exception e) {             e.printStackTrace( );         }         return con;     } } 

This application has two Struts actions. The class UserAction, which is mapped to the path /useraction, supports the selection of the username. The other action, UsernameSuggestAction, is mapped to the path /getSuggestionList; it supports the Ajax call that the <layout:suggest> tag uses to populate the suggestion list. Obviously, you could take this further: you could use an Ajax call to send the data to UserAction and then populate the form with other information, based on the username. I'll leave that as an exercise for the reader.

When the form is submitted, Struts invokes the UserAction action, which pulls the username out of the Struts form (UserForm) and then calls getUserInfo( ). In turn, getUserInfo( ) queries the database for the first name and last name of the selected user. Then the form values for lastName and firstName are set for the next JSP that will use it:

 ((UserForm)form).setFirstName(firstName); ((UserForm)form).setLastName(lastName); 

When results.jsp is invoked again, the UserForm object will be ready with the data for the username field.

8.1.7. Populating the Suggestion List

The UsernameSuggestAction class handles the Ajax call behind the <layout:suggest> tag. This class must extend fr.improve.struts.taglib.layout.suggest.SuggestAction and implement a method that returns a Collection. The contents of the Collection are used as the suggestions in the <layout:suggest> field; that list of suggestions should be an ArrayList of Strings.

The method used to get the Collection is set via the suggestAction parameter of the <layout:suggest> tag. Back in our usermanager.jsp file, we set this parameter to "/getSuggestionList", which matches the method name in UsernameSuggestAction (Example 8-8).

Example 8-8. The UsernameSuggestAction class

 public class UsernameSuggestAction extends SuggestAction {     public Collection getSuggestionList(HttpServletRequest in_request,             String in_word) {         Collection usernames = getUserSuggestions( );         ArrayList suggestions = new ArrayList( );         if (in_word != null && in_word.length( ) > 0) {             Iterator iter = usernames.iterator( );             while(iter.hasNext( )) {                 String currentWord = (String) iter.next( );                 if (currentWord.toLowerCase().startsWith(in_word.toLowerCase( )))                     suggestions.add(currentWord);             }         }         return suggestions;     }     private static Collection getUserSuggestions( ) {         ArrayList arrayList = null;         Connection con = DatabaseConnector.getConnection( );         try {             Statement statement = con.createStatement( );             String sqlString = "select username from users;";             ResultSet resultSet = statement.executeQuery(sqlString);             arrayList = new ArrayList( );             while (resultSet.next( )) {                 arrayList.add(resultSet.getString(1));             }         }         catch (Exception e) {             System.out.println("exception caught getting usernames");         }         finally {             if (con != null) {                 try {                     con.close( );                 }                 catch (SQLException e) {                 }             }         }         return arrayList;     } } 

In most cases, the values in the suggestion list should come from a data store. This example is no exception: the list is populated with a call to the private method getUserSuggestions( ). The getSuggestionList( ) method is adapted from the demo example for <layout:suggest> on the Struts-Layout web site.

8.1.8. Struts-Layout Is Cool Because...

Setting up a suggestion field using the Struts-Layout package is incredibly easy. This is one of the few frameworks that use Ajax without requiring any Ajax-specific coding: we didn't have to write any JavaScript at all. Unfortunately, it currently has only one Ajax-enabled tag, but I'm sure Struts-Layout will add more Ajax functionality in the future. Keep checking in, because this framework has a lot of potential.




Ajax on Java
Ajax on Java
ISBN: 0596101872
EAN: 2147483647
Year: 2007
Pages: 78

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