The difference between LookupDispatchAction and DispatchAction is that the actual method that gets called in LookupDispatchAction is based on a lookup of a key value instead of specifying the method name directly.

Details :

LookupDispatchAction is subclass of DispatchAction.
In case of DispatchAction, you have to declare the method name in the JSP page.
For Example :
http://localhost:8080/emp/empaction.do?step=add // IN CASE OF DispatchAction
here step=add , we are delaring method name in JSP.
or
<html:submit property="step">Add</html:submit> //IN CASE OF DispatchAction
so we can't use localization for button.


To over come both the issues below
a)method name declaration in JSP
b)can't use localization for button
We will go for LookupDispatchAction.

In the LookupDispatchAction :
For example :
If there are three operation like add, delete, update employee.
You can create three different Actions ?
AddEmpAction, DeleteEmpAction and UpdateEmpAction.
This is a valid approach, although not elegant since there might be duplication of code across
the Actions since they are related. LookupDispatchAction is the answer to this
problem. With LookupDispatchAction, you can combine all three Actions into one.

Example :
Step 1.
three buttons might be
<html:submit property="step">
<bean:message key="button.add"/>
</html:submit>
<html:submit property="step">
<bean:message key="button.delete"/>
</html:submit>
<html:submit property="step">
<bean:message key="button.update"/>
</html:submit>

//No need method name declaration in JSP . Button name from resource bundle.

Step 2.
In the the Resource Bundle. //Here you can add localization.
button.add=Add
button.delete=Delete
button.update=Update

Step 3.
Implement a method named getKeyMethodMap() in the subclass of the
LookupDispatchAction. The method returns a java.util.Map. The
keys used in the Map should be also used as keys in Message Resource
Bundle.

public class EmpAction extends LookupDispatchAction {

public Map getKeyMethodMap()
{
Map map = new HashMap();
map.put("button.add", "add");
map.put("button.delete", "delete");
map.put("button.update", "update");
}


public ActionForward add(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception
{
//your logic
mapping.findForward("add-success");
}

public ActionForward delete(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception
{
//your logic
mapping.findForward("delete-success");
}

public ActionForward update(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception
{
//your logic
mapping.findForward("update-success");
}

}

in struts-config.xml

<action path="/empaction"
input="/empform.jsp"
type="list.EmpAction"
parameter="step"
scope="request"
validate="false">
<forward name="add-success"
path="addEmpSuccess.jsp"
redirect="true"/>
<forward name="delete-success"
path="deleteEmpSuccess.jsp"
redirect="true"/>
<forward name="update-success"
path="updateEmpSuccess.jsp"
redirect="true"/>
</action>

for every form submission, LookupDispatchAction does the
reverse lookup on the resource bundle to get the key and then gets the method
whose name is associated with the key from
getKeyMethodmap().


Flow of LookupDispatchAction:
a) Form the button name "Add" get the key "button.add" fro resource bundle.
b) then in the Map getKeyMethodMap() find the value associated with the key "button.add".
c) value from the Map is "add" . then call add() method of the same action class.

There are two approaches available for the exception handling in struts.


Declarative:
Exceptions are defined in the struts-config.xml file and
if the exception occurs the control is automatically passed to the appropriate error page.
The <exception> tag is used to define the exception in the struts-config.xml file.

For Example : (( If RuntimeException in SaveEmpAaction class , control goes to exception.jsp)

<action path="/saveEmp"
type="com.techfaq.SaveEmpAaction"
input="/empform.jsp" >
<exception key="error.system" type="java.lang.RuntimeException" path="/exception.jsp" />
</action>

Where

Key: The key defines the key present in MessageResources.properties file to describe the exception occurred.

Type: The class of the exception occurred.

Path: The page where the control is to be followed in case exception occurred.

Handler: The exception handler which will be called before passing the control to the file specified in path attribute

OR


Defining the Exceptions Globally for the struts-config.xml : ( If RuntimeException in any Action class , control goes to exception.jsp)
<global-exceptions>
<exception key="error.system" type="java.lang.RuntimeException" path="/exception.jsp" />
</global-exceptions>


Programmatic:
In this approach the exceptions are caught using normal java language try/catch block and instead of showing the exception some meaningful messages are displayed.
In this approach the flow of control is also maintained by the programs.
The main drawback of the approach is the developer has to write the code for the flow of the application.
Struts follow MVC framework. So the JSP, Java and Action classes are organized and easily maintainable.
Struts offers many advantages to the application programmer while reducing the development time and making the manageability of the application easier.
Advantages of Struts :


Centralized Configuration :
Rather than hard coding information into java programs,many Struts values are represented in XML or property files.
Struts_config.xml file is the place from where you can get all information?s about your web application. This is organized.
Your Action class , Form bean and JSP page information is in Struts_config.xml so don't need to search . All info in one place.



Form Beans :
Don't need to set the form vales to your value object . When you want to capture data from a form ( In the servlet you do request.getParameter()).
In the struts you don't need to do explicitly request.getParameter(). Struts request processor will do for you. All the input data will be set to form bean.



Bean Tags :
Struts provides a set of custom JSP tags (bean:write,in particular) that let you easily output the properties of JavaBeans components.
Basically,these are concise and powerful variations of the standard jsp:useBean and jsp:getProperty tags.


HTML tags :
Struts provides a set of custom JSP tags to create HTML forms that are associated with JavaBeans components.


Form Field Validation :

Apache Struts has built-in capabilities for checking that form values are in the required format.
If values are missing or in an improper format,the form can be automatically redisplayed with error messages and with the previously entered values maintained.
This validation can be performed on the server (in Java),or both on the server and on the client (in JavaScript).
DynaActionForm is specialized subclass of ActionForm that allows the creation of form beans with dynamic sets of properties,
without requiring the developer to create a Java class for each type of form bean.
DynaActionForm eliminates the need of FormBean class and now the form bean definition can be written into the struts-config.xml file. So, i
t makes the FormBean declarative and this helps the programmer to reduce the development time.

For Example : you have a EmpForm and you don't want a java class (EmpForm).
EmpForm has propertis
firstName, lastName, country

In the struts-config.xml file , declare the form bean
<form-bean name="EmpForm"
type="org.apache.struts.action.DynaActionForm">
<form-property name="firstName" type="java.lang.String"/>
<form-property name="lastName" type="java.lang.String"/>
<form-property name="country" type="java.lang.String" />
</form-bean>

Add action mapping in the struts-config.xml file:

<action path="/saveEmp" type="com.techfaq.action.EmpSaveAction"
name="EmpForm"
scope="request"
validate="true"
input="/pages/empform.jsp">

<forward name="success" path="/jsp/success.jsp"/>
<forward name="failure" path="/jsp/error.jsp" />

</action>

In the Action class.
public class EmpSaveAction extends Action
{
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{

DynaActionForm empForm = (DynaActionForm)form;
// this is the way you can retrive the value which is set in the JSP Page
String firstName = (String)empForm.get("firstName");
String lastName = (String)empForm.get("lastName");
return mapping.findForward("success");
}
}
}

In the JSP page
<html:text property="firstName" size="30" maxlength="30"/>
<html:text property="lastName" size="30" maxlength="30"/>
There are two configuration files used.
One if called validator-rules.xml and the other is validation.xml.
This is example of server side validation :


validator-rules.xml :

The validator-rules.xml file defines the Validator definitions available for a given application.
The validator-rules.xml file acts as a template, defining all of the possible Validators that are available to an application.
Example validator-rules.xml File :
<form-validation>
<global>
<validator
name="required"
classname="org.apache.struts.util.StrutsValidator"
method="validateRequired"
methodparams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
msg="errors.required"/>

</global>
</form-validation>

validation.xml File :
The validation.xml file is where you couple the individual Validators defined in the validator-rules.xml to components within your application.
validation.xml File

<form-validation>
<formset>
<form name="empForm">
<field
property="firstName"
depends="required">
<arg0 key="label.firstName"/>
</field>

<field
property="lastName"
depends="required">
<arg0 key="label.lastName"/>
</field>
</form>
</formset>
</form-validation>

In the empForm firstName and lastName are the required filed.
So in the above configuration you can see we add for both firstName and lastName.
You can see depends="required" - "required" property is defind in validator-rules.xml.

In the resource bundle : application_resource.propertis file
label.firstName=First Name
label.lastName=Last Name

#Error messages used by the Validator
errors.required={0} is required.

Based on the validation.xml File configuration .
Error in jsp will be :
First Name is required.
Last Name is required.

{0} will be filled by (First Name or Last Name) because validation.xml above configuration you have defind <arg0 key="label.firstName"/>.
Step 1.
place validator-rules.xml and validation.xml in the WEB-INF directory.

Step 2.
Add the blow lines to struts-config.xml
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>

Step 3.
In the jsp add the tag
<html:errors />

Step 4.
Add
struts.jar
commons-beanutils.jar
commons-collections.jar
commons-digester.jar
commons-fileupload.jar
commons-lang.jar
commons-logging.jar
commons-validator.jar

into WEB-INF/lib directory

Explanation :

There are two configuration files used.
One if called validator-rules.xml and the other is validation.xml.
This is example of server side validation :


validator-rules.xml :

The validator-rules.xml file defines the Validator definitions available for a given application.
The validator-rules.xml file acts as a template, defining all of the possible Validators that are available to an application.
Example validator-rules.xml File :
<form-validation>
<global>
<validator
name="required"
classname="org.apache.struts.util.StrutsValidator"
method="validateRequired"
methodparams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
msg="errors.required"/>

</global>
</form-validation>

validation.xml File :
The validation.xml file is where you couple the individual Validators defined in the validator-rules.xml to components within your application.
validation.xml File

<form-validation>
<formset>
<form name="empForm">
<field
property="firstName"
depends="required">
<arg0 key="label.firstName"/>
</field>

<field
property="lastName"
depends="required">
<arg0 key="label.lastName"/>
</field>
</form>
</formset>
</form-validation>

In the empForm firstName and lastName are the required filed.
So in the above configuration you can see we add for both firstName and lastName.
You can see depends="required" - "required" property is defind in validator-rules.xml.

In the resource bundle : application_resource.propertis file
label.firstName=First Name
label.lastName=Last Name

#Error messages used by the Validator
errors.required={0} is required.

Based on the validation.xml File configuration .
Error in jsp will be :
First Name is required.
Last Name is required.

{0} will be filled by (First Name or Last Name) because validation.xml above configuration you have defind <arg0 key="label.firstName"/>.
The <html:javascript> tag to allow front-end validation based on the xml in validation.xml.

Validation Framework provides the functionality to validate the form data. It can be use to validate the data on the client side. Errors will be displayed like java script.

Struts has a class called ValidatorForm in org.apache.struts.validator package. This is a subclass of ActionForm and implements the validate() method. The validate() method invokes the Commons Validator, executes the rules using the two xml files (validator-rules.xml and validation.xml) and generates ActionErrors using the Message Resources defined in the struts-config.xml.
validator-rules.xml :
The validator-rules.xml file defines the Validator definitions available for a given application.
The validator-rules.xml file acts as a template, defining all of the possible Validators that are available to an application.
validation.xml File :
The validation.xml file is where you couple the individual Validators defined in the validator-rules.xml to components within your application.


Follow the below steps to setup Validation Framework in Struts (server side validation ).

Step 1. Add validator plugin into struts-config.xml

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

Step 3. In the JSP page (EmpForm.jsp)- Add onsubmit="return validateempForm(this);" and <html:javascript formName="empForm"/> for Client Side Java Script Validation.

<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:form>
<html:form action="/submitForm.do" method="post" onsubmit="return validateempForm(this);">
<html:errors/> // this is for error message from resource bundle in JSP
<html:text property="firstName" size="20" maxlength="50"/>
<html:text property="lastName" size="20" maxlength="50"/>
<html:submit >Save</html:submit>
<!-- Begin Validator Javascript Function-->
<html:javascript formName="empForm"/>
<!-- End of Validator Javascript Function-->
</html:form>


Step 4. Add Message Resources location in struts-config.xml

<!-- Message Resources --> <message-resources parameter="application_resource"/>

Step 5. In the the Resource Bundle. application_resource.properties file //Here you can add localization.

label.firstName=First Name
label.lastName=Last Name
errors.required={0} is required.


Step 7. In the EmpForm

package com.techfaq.form;
public class EmpForm extends ValidatorForm {
int empId;
String firstName;
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 int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
}

Step 6. In the validation.xml - The validation.xml file is where you couple the individual Validators defined in the validator-rules.xml to components within your application

<form-validation>
<formset>
<form name="empForm">
<field property="firstName" depends="required">
<arg0 key="label.firstName"/>
</field>
<field property="lastName" depends="required"> <arg0 key="label.lastName"/>
</field>
</form>
</formset>
</form-validation>


Step 6. In the validator-rules.xml - The validator-rules.xml file defines the Validator definitions available for a given application.

<form-validation>
<global>
<validator
name="required"
classname="org.apache.struts.util.StrutsValidator"
method="validateRequired"
methodparams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
msg="errors.required"/>
</global>
</form-validation>


Step 5. Add Action mapping and form entry into the stuts-confix.xml and validate="true" is for validation framework to validate the form input.

<?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>
<form-beans>
<form-bean name="EmpForm" type="com.techfaq.form.EmpForm"> </form-bean>
</form-beans>
<action-mappings>
<action path="/submitForm"
type="com.techfaq.action.EmpAction"
name="EmpForm"
scope="request"
validate="true" // This need for validation framework to validate the form input
input="EmpForm.jsp">
<forward name="success"
path="success.jsp"/>
<forward name="failure" path="failure.jsp" />
</action>
</action-mappings>
</struts-config>


Now in the browser type http://localhost:8080/testApp/EmpForm.jsp

Don't Enter firstName and lastName in the text box and submit the "Save" BUTTON. the RequestProcessor checks for the validateattribute in the ActionMapping.
If the validate is set to true, the RequestProcessor invokes the validate() method of the ValidatorForm instance.
If Validate fail the RequestProcessor looks for the input attribute and return to JSP page mentioned in input tag.
If Validate pass goto Action Class execute() method..
If Validate fail , In the browser (EmpForm.jsp) you can see. Java Script pop up Message:


First Name is required.
Last Name is required.


In the empForm firstName and lastName are the required filed. So in the above configuration you can see we add for both firstName and lastName. You can see depends="required" - "required" property is defind in validator-rules.xml. In the resource bundle : application_resource.propertis file
label.firstName=First Name
label.lastName=Last Name
#Error messages used by the Validator
errors.required={0} is required.
{0} will be filled by (First Name or Last Name) because validation.xml above configuration you have defind
<arg0 key="label.lastName"/>. and <arg0 key="label.lastName"/>.

Add <html:errors/> to your jsp page.

validate() : Used to validate properties after they have been populated; Called before FormBean is handed to Action. Returns a collection of ActionError as ActionErrors. Following is the method signature for the validate() method.

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
                        
ActionErrors errors = new ActionErrors();
if ( StringUtils.isNullOrEmpty(username) && StringUtils.isNullOrEmpty(password)){
                    errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.usernamepassword.required"));
                }
return errors;
}

You have to add the error key from resource bundle.

error.usernamepassword.required : key from resource bundle properties file.

In the JSP , you have to add the below tag to display the error message from validate() method.
<html:errors />
The class org.apache.struts.action.ActionServlet is the called the ActionServlet. In the the Jakarta Struts Framework this class plays the role of controller. All the requests to the server goes through the controller. Controller is responsible for handling all the requests.

Struts Flow start with ActionServlet then call to process() method of RequestProcessor.

Step 1. Load ActionServlet using load-on-startup and do the following tasks.

Any struts web application contain the ActionServlet configuration in web.xml file.
On load-on-startup the servlet container Instantiate the ActionServlet .
First Task by ActionServlet : The ActionServlet takes the Struts Config file name as an init-param.
At startup, in the init() method, the ActionServlet reads the Struts Config file and load into memory.
Second Task by ActionServlet : If the user types http://localhost:8080/app/submitForm.do in the browser URL bar, the URL will be intercepted and processed by the ActionServlet since the URL has a pattern *.do, with a suffix of "do". Because servlet-mapping is
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Third Task by ActionServlet : Then ActionServlet delegates the request handling to another class called RequestProcessor by invoking its process() method.

Step 2. ActionServlet calls process() method of RequestProcessor
Message Resources Definitions file are simple .properties files and these files contains the messages that can be used in the struts project. Message Resources Definitions files can be added to the struts-config.xml file through <message-resources /> tag.
Example:

<message-resources parameter="application_resource"/>

application_resource is properties file.

application_resource.properties looks like
error.vendor.location = <li> Error at Vendor Location.
error.Recordingurl.needed = <li> URL is Mandatory for Other Vendor.
An Action class in the struts application extends Struts 'org.apache.struts.action.Action" Class.

Action class acts as wrapper around the business logic and provides an inteface to the application's Model layer.

An Action works as an adapter between the contents of an incoming HTTP request and the business logic that corresponds to it.

Then the struts controller (ActionServlet) slects an appropriate Action and Request Processor creates an instance if necessary,

and finally calls execute method of Action class.

To use the Action, we need to Subclass and overwrite the execute() method. and your bussiness login in execute() method.

The return type of the execute method is ActionForward which is used by the Struts Framework to forward the request to the JSP as per the value of the returned ActionForward object.

ActionForward JSP from struts_config.xml file.



Developing our Action Class :



Our Action class (EmpAction.java) is simple class that only forwards the success.jsp.

Our Action class returns the ActionForward called "success", which is defined in the struts-config.xml file (action mapping is show later in this page).

Here is code of our Action Class

public class EmpAction extends Action

{

public ActionForward execute(

ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response) throws Exception{

return mapping.findForward("success");

}

}



mapping.findForward("success"); forward to JSP mentioned in struts_config.xml.

struts_config.xml configuration is :



<action

path="/EmpAction"

type="com.techfaq.EmpAction">

<forward name="success" path="/success.jsp"/>

</action>

mapping.findForward("success") method forward to success.jsp (mentioned in struts_config.xml);





Here is the signature of the execute() method Action Class.



public ActionForward execute(ActionMapping mapping,

ActionForm form,

javax.servlet.http.HttpServletRequest request,

javax.servlet.http.HttpServletResponse response)

throws java.lang.Exception



Where

mapping - The ActionMapping used to select this instance

form - The optional ActionForm bean for this request (if any)

request - The HTTP request we are processing

response - The HTTP response we are creating

Throws:

Action class throws java.lang.Exception - if the application business logic throws an exception



In the browser : http://localhost:8080/testApp/EmpAction.do

This will call to execute() method of EmpAction and after that based on mapping.findForward("success") forward to success.jsp.
An ActionForm is a JavaBean that extends org.apache.struts.action.ActionForm. ActionForm maintains the session state for web application and the ActionForm object is automatically populated (by RequestProcessor)on the server side with data entered from a form on the client side.

If your JSP contain two fields
username and password
<html:text property = "username" maxlength = "60" >
<html:password property = "password" maxlength = "60" />

Then the ActionForm is
public class LogonForm extends ActionForm{
    
        /**
     * Password entered by user
     */
     private String password = null;
     /**
     * Username entered by user
     */
     private String username = null;
/**
         * @return Returns the password.
         */
        public String getPassword() {
            return password;
        }
        /**
         * @param password The password to set.
         */
        public void setPassword(String password) {
            this.password = password;
        }
        /**
         * @return Returns the username.
         */
        public String getUsername() {
            return username;
        }
        /**
         * @param username The username to set.
         */
        public void setUsername(String username) {
            this.username = username;
        }
}

When you enter data to your JSP and submit the request processor set the data to LogonForm. You don't need to do request.getParameter("username") etc,
Struts follow Model View Controller Architecture. Components is divided based on MVC.

Controller :

The ActionServlet and the collaborating classes are RequestProcessor, ActionForm, Action, ActionMapping and ActionForward in in Controller category.

ActionServlet :

The central component of the Struts Controller is the ActionServlet. It is a concrete class and extends the javax.servlet.HttpServlet. It performs two important things.
1. On startup, its reads the Struts Configuration file and loads it into memory in the init() method.
2. In the doGet() and doPost() methods, it intercepts HTTP request and handles it appropriately.


View :

The View category contains utility classes ? variety of custom tags (html,bean,logic) and JSP.

Model :

Struts does not offer any components in the Model Category. Your Action class contains business logic may be model.
The class org.apache.struts.action.ActionServlet is the called the ActionServlet. In the the Jakarta Struts Framework this class plays the role of controller. All the requests to the server goes through the controller. Controller is responsible for handling all the requests.



Struts Flow start with ActionServlet then call to process() method of RequestProcessor.



Step 1. Load ActionServlet using load-on-startup and do the following tasks.



Any struts web application contain the ActionServlet configuration in web.xml file.

On load-on-startup the servlet container Instantiate the ActionServlet .

First Task by ActionServlet : The ActionServlet takes the Struts Config file name as an init-param.

At startup, in the init() method, the ActionServlet reads the Struts Config file and load into memory.

Second Task by ActionServlet : If the user types http://localhost:8080/app/submitForm.do in the browser URL bar, the URL will be intercepted and processed by the ActionServlet since the URL has a pattern *.do, with a suffix of "do". Because servlet-mapping is

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

Third Task by ActionServlet : Then ActionServlet delegates the request handling to another class called RequestProcessor by invoking its process() method.



Step 2. ActionServlet calls process() method of RequestProcessor
The different kinds of actions in Struts are:

ForwardAction
IncludeAction
DispatchAction
LookupDispatchAction
SwitchAction