Exforsys.com
 

Sponsored Links

 

Jakarta Struts Tutorials

 
Home Tech Articles Jakarta Struts
 

Struts Lesson III

 

LESSON III - Introduction

This lesson assumes you understand the basic of Struts. If you are new to Struts you should start with Lesson I and Lesson II.

NOTE:I've decided now that I really hate DynaActionForms. So, although I demonstrate their use here, I strongly discourage their use.

The main reason I am not fond of them is because there are no compile-time checks when using them. In other words, to manually set a DynaForm field you do something like: yourDynaForm.set("myProperty", myValue );. Well this will always compile, but what if "myProperty" really isn't the field name that you have defined? You won't know until run time. Bugs can easily creep into code that are more difficult to track down using DynaForms. More than likely you also usually end up having to build a regular form bean which extends a DynaActionForm because you realize later on that you have to over-ride the reset method or you may even need some custom validation in the validate method. So now the only advantage you've gained with your DynaForm is you didn't have to create set/get methods. But how difficult is that? Most IDEs will do that for you anyway. So, save yourself the later headaches and just use regular ActionForms.

Concepts introduced in Lesson III:

DynaActionForm (DynaValidatorForm)
Declarative Exception Handling
Validation made easy
html:multibox tag

This application mimics the business requirement of inserting and updating an employee. The flow of this example doesn't mimic what you would really have set up in real life, since in real life you'd probably choose from a list of employees to update. This example, since it doesn't do any real business logic, simply lets you update the employee you just pretended to insert.

This Lesson is a lot like Lesson II in functionality except the flow is a bit different. After an insert of an Employee you are forwarded to the filled out employeeForm and you could resubmit it as an update. The confirmation page that you saw in Lesson II now is displayed only after you do an update

LESSON III - 1 - Setup

These Lessons assume you are using Tomcat 4.1 and have downloaded Struts 1.1-rc2 or greater.

Create following directory structure under tomcat:


webapps
|
|
struts_lesson_3
|
|
--- WEB-INF
|
|--- classes
| |
| --- net
| |
| -- exforsys
|--- lib
|
--- src
|
--- net
|
-- exforsys


Add The Appropriate Struts Files:

In the struts/contrib/struts-el/lib you should find the following files which you need to add to your struts_lesson_3/WEB-INF directory:

c.tld
struts-bean-el.tld
struts-html-el.tld
struts-logic-el.tld

From the same struts/contrib/struts-el/lib copy the following jar files to your struts_lesson_3/WEB-INF/lib directory:

commons-beanutils.jar
commons-collections.jar
commons-digester.jar
commons-logging.jar
commons-validator.jar
jstl.jar
standard.jar
struts-el.jar
struts.jar

(Note we are using the tld files and jars in the contributed struts-el directory since this will force us to use the standard JSTL tags whenever possible).

In the main struts/lib directory you'll find:
validation-rules.xml
commons-validator.jar
Both of these files need to also be added to your struts_lesson_3/WEB-INF/lib directory.

Create web.xml:

Finally, we need to make sure we have a web.xml file in our struts_lesson_3/WEB-INF/ directory. The web.xml looks exactly the same as it did in the other two lessons except that we changed the display name to struts lesson 3.

<?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>Struts lesson 3</display-name>

<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>index.jsp</welcome-file>
</welcome-file-list>

<!-- tag libs -->
<taglib>
<taglib-uri>struts/bean-el</taglib-uri>
<taglib-location>/WEB-INF/struts-bean-el.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>struts/html-el</taglib-uri>
<taglib-location>/WEB-INF/struts-html-el.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>struts/logic-el</taglib-uri>
<taglib-location>/WEB-INF/struts-logic-el.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>jstl/c</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>

</web-app>


LESSON III - 2 - Create Beans

We need a Data Transfer Object to store the Employee information that our business layer can use (fields with the correct data types as opposed to just String properties that ActionForm beans hold). We also need to create a few other objects. Create all of these objects as listed below:

EmployeeDTO:

package net.exforsys;

public class EmployeeDTO {
private String name;
private int age;
private int department;
private String[] flavorIDs;

public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setDepartment(int department) {
this.department = department;
}
public void setFlavorIDs(String[] flavorIDs) {
this.flavorIDs = flavorIDs;
}

public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getDepartment() {
return department;
}
public String[] getFlavorIDs() {
return flavorIDs;
}
}

DepartmentBean:

package net.exforsys;

public class DepartmentBean {

private int id;
private String description;

public DepartmentBean() {
}
public DepartmentBean( int id, String description ) {
this.id = id;
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

FlavorBean:

package net.exforsys;

public class FlavorBean {
private String flavorID;
private String description;

public FlavorBean() {}
public FlavorBean( String flavorID, String description ) {
this.flavorID = flavorID;
this.description = description;
}
public void setFlavorID(String flavorID) {
this.flavorID = flavorID;
}
public String getFlavorID() {
return flavorID;
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}

DatabaseException:

package net.exforsys;

public class DatabaseException extends Exception {
public DatabaseException() {
super();
}
public DatabaseException(String message) {
super(message);
}
}

LESSON III - 3 - Create EmployeeService

The EmployeeService class is an object that represents our bridge to the Model layer of our architecture. You can build your business/model components in many different ways, using many different design patterns. Since Struts really only deals with the View and Controller aspects of an MVC architecture we only need a basic class here to mimic some business requirements that, in real life, we would handle using other components. The EmployeeService is going to take care of doing our Employee insert and update operation. For simplicity's sake we are also adding a method to return a Collection of departments and another to return a Collection of flavors. You can also test what happens when a DatabaseException is thrown by uncommenting out the appropriate line in either the mimicInsert or mimicUpdate methods.

EmployeeService:

package net.exforsys;

import java.util.Collection;
import java.util.ArrayList;

public class EmployeeService {
public EmployeeDTO insertEmployee( EmployeeDTO employee ) throws DatabaseException {
//in real life call other business classes to do insert
try {
mimicInsert( employee );
}
catch( DatabaseException de ) {
//log error
throw de;
}
return employee;
}

public EmployeeDTO updateEmployee( EmployeeDTO employee ) throws DatabaseException {
//in real life call other business classes to do update
try {
mimicUpdate( employee );
}
catch( DatabaseException de ) {
//log error
throw de;
}
return employee;
}

//this wouldn't be in this service class, but would be in some other business class/DAO
private void mimicInsert( EmployeeDTO employee ) throws DatabaseException {
//to test an Exception thrown uncomment line below
//throw new DatabaseException("Error trying to insert Employee");
}
//this wouldn't be in this service class, but would be in some other business class/DAO
private void mimicUpdate( EmployeeDTO employee ) throws DatabaseException {
//to test an Exception thrown uncomment line below
//throw new DatabaseException("Error trying to update Employee");
}

public Collection getDepartments() {
//call business layer to return Collection of Department beans
//since we aren't dealing with the model layer, we'll mimic it here
ArrayList list = new ArrayList(3);
list.add( new DepartmentBean( 1, "Accounting"));
list.add( new DepartmentBean( 2, "IT"));
list.add( new DepartmentBean( 3, "Shipping"));
return list;
}
public Collection getFlavors() {
//call business layer to return Collection of Flavors
//since we aren't dealing with the model layer, we'll mimic it here
ArrayList list = new ArrayList(3);
list.add( new FlavorBean( "101", "Chocolate"));
list.add( new FlavorBean( "201", "Vanilla"));
list.add( new FlavorBean( "500", "Strawberry"));
return list;
}
}

LESSON III - 4 - Setup DynaActionForm (DynaValidatorForm)

In previous lessons we created an EmployeeForm object which extended the Struts ActionForm. There is, however, a much easier way to create ActionForm objects by using DynaActionForm which allows you to configure the bean in the struts-config.xml file. We are going to use a subclass of DynaActionForm called a DynaValidatorForm which provides greater functionality when used with the validation framework.

NOTE:I've decided now that I really hate DynaActionForms. So, although I demonstrate their use here, I strongly discourage their use. The main reason I am not fond of them is because there are no compile-time checks when using them. In other words, to manually set a DynaForm field you do something like: yourDynaForm.set("myProperty", myValue );. Well this will always compile, but what if "myProperty" really isn't the field name that you have defined? You won't know until run time. Bugs can easily creep into code that are more difficult to track down using DynaForms. More than likely you also usually end up having to build a regular form bean which extends a DynaActionForm because you realize later on that you have to over-ride the reset method or you may even need some custom validation in the validate method. So now the only advantage you've gained with your DynaForm is you didn't have to create set/get methods. But how difficult is that? Most IDEs will do that for you anyway. So, save yourself the later headaches and just use regular ActionForms.As we proceed through the rest of these steps we'll be building the struts-config.xml file as we go along.

Create first part of struts-config.xml (declare DynaValidatorForm ):

<!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 Bean Definitions -->
<form-beans>
<form-bean name="employeeForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="name" type="java.lang.String"/>
<form-property name="age" type="java.lang.String"/>
<form-property name="department" type="java.lang.String" initial="2" />
<form-property name="flavorIDs" type="java.lang.String[]"/>
<form-property name="methodToCall" type="java.lang.String"/>
</form-bean>
</form-beans>

Looking at the form-bean definition above you see that we are using type org.apache.struts.validator.DynaValidatorForm. Magically Struts will make sure to create this bean for us using the form-property fields defined. Since we are actually going to capture more than one ice cream flavor that an employee likes, flavorIDs is defined as a String array. The "methodToCall" property is a property that we are going to use in our DispatchAction class (more about that later). Remember, just like when using the standard ActionForm, you should keep these form fields set as Strings since an HTML form will only submit the request information in String format. This DynaValidatorForm is used just like a normal ActionForm when it comes to how we define it's use in our action mappings. The only 'tricky' thing is that standard getter and setters are not made since the DynaActionForms are backed by a HashMap. In order to get fields out of the DynaActionForm you would do: String age = (String)formBean.get("age"); Similarly, if you need to define a property: formBean.set("age","33"); You'll see an example of this usage in the SetUpEmployeeAction in the next step. If you want, though, you could set initial values for the properties as you see done above for the department property. This will always set the initial value of the department id to "2."

LESSON III - 5 - Create SetUpEmployeeAction

The SetUpEmployeeAction will map to /setUpEmployeeAction. First let's continue adding to the struts-config.xml file.

Add global-forwards and /setUpEmloyeeForm mapping: <!-- Global forwards -->
<global-forwards>
<forward name="error" path="/error.jsp"/>
</global-forwards>

<!-- Action Mapping Definitions -->
<action-mappings>

<action path="/setUpEmployeeForm"
type="net.exforsys.SetUpEmployeeAction"
name="employeeForm"
scope="request"
validate="false">
<forward
name="continue"
path="/employeeForm.jsp"/>
</action>

Our first action-mapping directs us to the SetUpEmployeeAction. If you looked at Lesson 2 you will see that this mapping is almost exactly the same. The only difference is behind the scenes where "employeeForm" is now a DynaValidatorForm instead of the basic ActionForm. Now we can create the actual SetUpEmployeeAction.

Create SetUpEmloyeeAction:

package net.exforsys;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.DynaActionForm;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.util.Collection;

public final class SetUpEmployeeAction extends Action {

public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {


EmployeeService service = new EmployeeService();
Collection departments = service.getDepartments();
Collection flavors = service.getFlavors();
HttpSession session = request.getSession();
session.setAttribute( "departments", departments );
session.setAttribute( "flavors", flavors );
DynaActionForm employeeForm = (DynaActionForm)form;
employeeForm.set( "methodToCall", "insert" );
return (mapping.findForward("continue"));
}
}

This Action is almost identical to the SetUpEmployeeAction in Lessons I and II. Pay attention to the cast of the ActionForm into the type DynaActionForm and the setting of the 'methodToCall' property:DynaActionForm employeeForm = (DynaActionForm)form; employeeForm.set( "methodToCall", "insert" ); The methodToCall being set to "insert" will make more sense after the next step in our lesson. (What we are going to do is use this property to set a hidden form field to "insert" so that our DispatchAction will know to do an insert when the employeeForm.jsp is submitted). Also note that we are not setting the 'department' property here since we set up that an initial value in our DynaValidatorForm.

NOTE: It's not really a good idea to hard code your forwards as String literals like I have been doing. It's better to define these as constants in some constants Interface. If ever you decide to change the names that you use for these forwards in your struts-config.xml file you then only need to change the forward definitions in one other class.

LESSON III - 6 - DispatchAction / Declarative Exceptions

Normally you set up each action event to always correspond to a unique Action class. There is nothing wrong with doing this but if you want to condense related events into one Action class you can do so using a DipatchAction (or one of it's subclasses like LookupDispatchAction). Typical CRUD events (create, retrieve, update, and delete) can be seen as related events. In this example we have an option for inserting an employee and also for updating an employee. We could have just kept the Lesson II InsertEmployeeAction and then created another UpdateEmployeeAction for handling the update request, but instead we are going to put both of these events into one EmployeeDispatchAction. The DipatchAction works by using a parameter defined in your action-mapping to figure out which method to call in the DispatchAction class. In our action-mapping that submits to EmployeeDispatchAction we have the parameter defined as "methodToCall." (Many examples call this paramter "dispatch" or "action". I just chose to call it methodToCall so that you get the idea that this paramter will associate with a method by the same name in your DispatchAction). We'll define our action-mapping for the EmployeeDispatchAction first. Any call to /do/employeeAction is going to submit to our EmployeeDipatchAction.

Define employeeAction mapping in struts-config.xml: <!-- handles dispatch events of "insert" and "update" -->

<action path="/employeeAction"
type="net.exforsys.EmployeeDispatchAction"
name="employeeForm"
scope="request"
validate="true"
parameter="methodToCall"
input="/employeeForm.jsp"
>
<exception
key="exception.database.error"
type="net.exforsys.DatabaseException"
path="/error.jsp"/>
<forward
name="insertSuccess"
path="/employeeForm.jsp"/>
<forward
name="updateSuccess"
path="/confirmation.jsp"/>
</action>

In the case above all /do/employeeAction requests are going to be handled by the EmployeDispatchAction. Validate is set to "true" so that our employeeForm will be validated. Notice that there is a 'parameter' attribute defined and also two possible forwards are declared. In this example if the insert is successful we are forwarding the user right back to the employeeForm.jsp so that the user can update the employee if they like. If an update is successful the user is forwarded to a confirmation page. Also notice the declaration of the DatabaseException here directly in the action-mapping. This is called declarative Exception handling. In your Action class, if an Exception is thrown it will propagate up the chain to the base Action class where an attempt will be made to find the type of Exception in the mapping for that action. If it does not find one there, it will then look for that Exception defined globally in the struts-config.xml file. The declarative Exception handling will also create an ActionError message for you based on the key lookup in your resources file. (In the case above it would probably make more sense to declare the DatabaseException as a global exception since it is forwarding to a generic error.jsp file and other Actions will often throw the same Exception). Using declarative exceptions is great since it enables you to avoid having to code try/catch blocks in your actions and having to type redundant error handling code all over the place. Look back at the InsertEmployeAction code and compare it to the new EmployeeDispatchAction you are now going to create.

Create EmployeeDispatchAction:

package net.exforsys;

import org.apache.struts.action.*;
import org.apache.struts.actions.DispatchAction;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public final class EmployeeDispatchAction extends DispatchAction {

public ActionForward insert(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
EmployeeService service = new EmployeeService();
DynaActionForm employeeForm = (DynaActionForm)form;
EmployeeDTO employeeDTO = new EmployeeDTO();
BeanUtils.copyProperties( employeeDTO, employeeForm );
service.insertEmployee( employeeDTO );
ActionMessages messages = new ActionMessages();
ActionMessage message = new ActionMessage("message.employee.insert.success");
messages.add( ActionMessages.GLOBAL_MESSAGE, message );
saveMessages( request, messages );
employeeForm.set("methodToCall","update");
return (mapping.findForward("insertSuccess"));
}

public ActionForward update(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
EmployeeService service = new EmployeeService();
DynaActionForm employeeForm = (DynaActionForm)form;
EmployeeDTO employeeDTO = new EmployeeDTO();
BeanUtils.copyProperties( employeeDTO, employeeForm );
service.updateEmployee( employeeDTO );
ActionMessages messages = new ActionMessages();
ActionMessage message = new ActionMessage("message.employee.update.success");
messages.add( ActionMessages.GLOBAL_MESSAGE, message );
saveMessages( request, messages );
return (mapping.findForward("updateSuccess"));
}
}

Notice how instead of having one execute method, we have the methods "insert" and "update." The superclass DispatchAction still has an execute method which you inherit but ultimately the appropriate method in your EmployeeDispatchAction will get called based on the value of the parameter associated for this Action (in our example we used the parameter name "methodToCall"). In our SetUpEmployeeAtion we first set methodToCall with the value of "insert" which we will see used as a hidden variable on our employeeForm.jsp. When the form submits it then knows to call the "insert" method in our EmployeeDispatchAction. If you look at the insert method you will see this line: employeeForm.set("methodToCall","update"); After the insert is completed, and before we forward back to the employeeForm.jsp page, we are setting the form field "methodToCall" to "update." Hence the next time the form is submitted it will end up calling the update method in this EmployeeDispatchAction instead of insert. Notice the try/catch blocks are not necessary to catch and create an ActionErrorMesssage for the DatabaseException that may get thrown by service.insertEmployee() and service.updateEmployee(). Note: It's a good idea to have all of your Actions and DispatchAction classes extend a BaseAction or BaseDispatchAction. Common functionality could be added to these Base classes that all Action/DispatchAction subclasses could use, usually by adding some tasks to an overridden execute method).

LESSON III - 7 - Create Application Resources

Create the ApplicationResources.properties file and place in struts_lesson_3/WEB-INF/classes directory.

Also a good idea to include it in in struts_lesson_3/WEB-INF/src directory as well.

Create ApplicationResources.properties: #-- titles

title.error=ERROR PAGE
title.employeeApp=EMPLOYEE APPLICATION
title.employee.employeeform=EMPLOYEE FORM
title.employee.confirmation=CONFIRMATION
title.employee.insert=ADD AN EMPLOYEE
title.employee.update=UPDATE AN EMPLOYEE

#--display names
name.displayname=Name
age.displayname=Age

#-- messages
message.employee.update.success=Successful update of Employee.
message.employee.insert.success=Successfully added Employee.

#-- exceptions
exception.database.error=Problem occurred when performing database operation.Error Message: {0}

#-- validation errors
errors.required={0} is required.
errors.integer={0} must be a whole number.

#-- errors headers
errors.validation.header=Validation Error:

#-- buttons --
button.submit=SUBMIT
button.update=UPDATE

Notice the exception.database.error declaration. This is the key we provided in our declarative exception for DatabaseException in the struts-config.xml file. The actual error message itself will be passed in to the {0} argument. The next step will explain our validation framework. Take a look at the two validation error declarations above. You'll see how those fit in after reviewing the next step.

LESSON III - 8 - Validation Made Easy

Using the org.apache.struts.validator package makes validating very simple and efficient. A default validation-rules.xml file comes with Struts which provides rules for validating many common situations. In order to use the framework you need to create a validation.xml file and define that you are using the validator plugin in the struts-config.xml.

Complete the struts-config.xml file: <!-- message resources -->
<message-resources
parameter="ApplicationResources"
null="false" />

<!-- plugins -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>

</struts-config>.
Create validation.xml file and place it in struts_lesson_3/WEB-INF/: <form-validation>
<formset>
<form name="employeeForm">
<field property="name"
depends="required">
<arg0 key="name.displayname"/>
</field>
<field property="age"
depends="required,integer">
<arg0 key="age.displayname"/>
</field>
</form>
</formset>
</form-validation>

Setting validate="true" for an action-mapping to employeeForm will execute validation based on the fields declared in the validation.xml file. The validation above declares that we are going to validate "name" and "age." The possible values for the 'depends' attributes are those that are delcared in the validation-rules.xml. (Of course you can add your own plugins to the framework as well, but most of the basic validations are already defined for you). In our example we are defining both 'name' and 'age' with the 'required' value, and for age we are also providing 'integer.' Upon submission of the employeeForm both fields will be checked that they are not null or left blank and age will also be checked to be sure it is a valid number. One thing you have to make sure of is that you provide the necessary key/value pairs in your ApplicationResources file for the validation errors that could occur. If you go back to step 7 you see we defined: errors.required={0} is required.errors.integer={0} must be a whole number. These are global errors that we could use for all of our validations. The key that we provide for arg0 in the validation.xml file definitions will substitute the proper value in place of {0} if an error occurs. (In the ApplicationResources file you will see name.displayname and age.displayname defined and those values will be substituted for {0} in the appropriate validation).

LESSON III - 9 - employeeForm.jsp

The employeeForm.jsp is going to be used for both our employee insert and employee update. You will see logic tags ( c:choose ) for different information to display based on whether the form is used for an insert or an update. Our Action classes are responsible for setting the hidden form field "methodToCall" to either "insert" or "update" before the user is forwarded to this form. You will also see the use of the Strut's html:multibox tag which is a great tag for setting up multiple checkboxes. Note: checkboxes can be tricky if your form bean will ever have session scope. If that is the case, you will need to reset all checkboxes to false in the reset method of your form bean. Using a DynaActionForm this means you will have to use a subclass of DynaActionForm and create the reset method in this class. You'll then use this subclass as your type definition in defining the DynaActionForm properties as usual in your struts-config.xml file.

Create employeeForm.jsp:

<%@ taglib uri="struts/bean-el" prefix="bean" %>

<%@ taglib uri="struts/html-el" prefix="html" %>
<%@ taglib uri="struts/logic-el" prefix="logic" %>
<%@ taglib uri="jstl/c" prefix="c" %>
<html>
<head>
<link href="<html:rewrite page="/struts.css" />" rel="stylesheet" type="text/css">
<title><bean:message key="title.employee.employeeform"/></title>
</head>
<body>

<c:choose>
<c:when test="${employeeForm.map.methodToCall == 'insert'}">
<h1><bean:message key="title.employee.insert"/></h1>
</c:when>
<c:otherwise>
<h1><bean:message key="title.employee.update"/></h1>
</c:otherwise>
</c:choose>

<logic:messagesPresent>
<span id="errorsHeader"><bean:message key="errors.validation.header"/></span>
<html:messages id="error">
<li><c:out value="${error}"/></li>
</html:messages>
<hr>
</logic:messagesPresent>

<logic:messagesPresent message="true">
<html:messages id="message" message="true">
<span id="success"><c:out value="${message}"/></span><br>
</html:messages>
</logic:messagesPresent>

<html:form action="employeeAction" focus="name">
<table>
<tr>
<td >Name:</td>
<td><html:text property="name"/></td>
</tr>
<tr>
<td>Age:</td>
<td><html:text property="age"/></td>
</tr>
<tr>
<td>Department:</td>
<td>
<html:select name="employeeForm" property="department">
<html:options collection="departments" property="id" labelProperty="description"/>
</html:select>
</td>
</tr>
<tr>
<td>Favorite ice cream flavors:</td>
<td>
<c:forEach var="flavor" items="${flavors}">
<html:multibox name="employeeForm" property="flavorIDs">
<c:out value="${flavor.flavorID}"/>
</html:multibox>
<c:out value="${flavor.description}"/>

</c:forEach>
</td>
</tr>
</table>
<html:hidden name="employeeForm" property="methodToCall"/>

<c:choose>
<c:when test="${employeeForm.map.methodToCall == 'insert'}">
<html:submit><bean:message key="button.submit"/></html:submit>
</c:when>
<c:otherwise>
<html:submit><bean:message key="button.update"/></html:submit>
</c:otherwise>
</c:choose>

</html:form>
</body>
</html>

You might be wondering why there are two different versions of the logic:messagesPresent tag blocks. The reason is that one set is used to display ActionErrors which, in this example could be on the page when validation errors are present, and the other other set is used to display normal ActionMessages which, in this case, would be a successful insert message. By adding message="true" to the messages tags we make sure that only ActionMessages are displayed. (Leaving out the message="true" means only ActionErrors will be displayed if present).

LESSON III - 10 - Create other JSPs

Adding these remaining files completes our application and lesson. Hopefully you found the lesson helpful. These remaining files are all placed in struts_lesson_3/ and should be easy to understand.

Pay attention to the html:messages tags.

struts.css:

body { font-family: arial,sans-serif;
color: black;
background-color: #F1FFD2;
font-size: 12pt;
}
#success { color: green; font-weight: bold; }
#error { color: red; font-weight: bold; }
#errorsHeader { color: red; font-weight: bold; font-size: 13pt; }
index.jsp: <%@ taglib uri="struts/bean-el" prefix="bean" %>
<%@ taglib uri="struts/html-el" prefix="html" %>
<html>
<head>
<link href="<html:rewrite page="/struts.css" />" rel="stylesheet" type="text/css">
<title><bean:message key="title.employeeApp"/></title>
</head>
<body>
<h1><bean:message key="title.employeeApp"/></h1>
<br>
<html:link page="/do/setUpEmployeeForm">Add An Employee</html:link>
</body>
</html>

confirmation.jsp:

<%@ taglib uri="struts/bean-el" prefix="bean" %>
<%@ taglib uri="struts/html-el" prefix="html" %>
<%@ taglib uri="struts/logic-el" prefix="logic" %>
<%@ taglib uri="jstl/c" prefix="c" %>
<html>
<head>
<title><bean:message key="title.employee.confirmation"/></title>
<link href="<html:rewrite page="/struts.css" />" rel="stylesheet" type="text/css">
</head>
<body>
<h1><bean:message key="title.employee.confirmation"/></h1>
<br>
<logic:messagesPresent message="true">
<html:messages id="message" message="true">
<span id="success"><c:out value="${message}"/></span><br>
</html:messages>
</logic:messagesPresent>
</body>
</html>
error.jsp: <%@ taglib uri="struts/bean-el" prefix="bean" %>
<%@ taglib uri="struts/html-el" prefix="html" %>
<%@ taglib uri="jstl/c" prefix="c" %>
<html>
<head>
<link href="<html:rewrite page="/struts.css" />" rel="stylesheet" type="text/css">
<title><bean:message key="title.error"/></title>
</head>
<body>
<h1><bean:message key="title.error"/></h1>

<html:messages id="error">
<span id="error"><c:out value="${error}" escapeXml="false"/></span><br>
</html:messages>
</body>
</html>

End of Lession III


Read Next: Struts Lesson I : Your first Struts application



 

 

Comments



Post Your Comment:

Members Please Login
Your Name:*
e-mail ID:(required for notification)*
Image Verification: 
 
 Subscribe    

Sponsored Links

 

Subscribe via RSS


Get Daily Updates via Subscribe to Exforsys Free Training via email


Get Latest Free Training Updates delivered directly to your Inbox...

Enter your email address:


 

Subscribe to Exforsys Free Training via RSS
 

 
Partners -  Privacy and Legal Policy -  Site News -  Contact   Sitemap  

Copyright © 2000 - 2010 exforsys.com. All Rights Reserved

Page copy protected against web site content infringement by Copyscape