Showing posts with label Struts Actions Examples. Show all posts
Showing posts with label Struts Actions Examples. Show all posts

STRUTS INTERNATIONALIZATION

In this tutorial we shall see how to implement Internationalization (abbreviated as I18N) in Struts.

The Multinational Corporations have their branches in various parts of the world. so, they must provide products and services to their clients and customers in their traditional way. The customers will expect the product to work in their native languages especially the date, time, currency etc.,. So, the we should not make any assumptions about their clients region or language. If such assumptions become invalid, we have to re-engineer the applications.

Internationalization or I18N is the process of designing the software to support multiple languages and regions, so that we don't need to re-engineer the applications every language or country needs to be supported.

Struts provides various locale sensitive JSP tags which can be used to make the applications simpler. With this short introduction we shall see how to implement i18n in a Simple JSP file of Struts.


g:\>md localedemo
g:\>cd localedemo
g:\localedemo>edit localedemo.jsp

// g:\localedemo\localedemo.jsp

<%@ page language="java" %>

<%@ 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 locale="true">


message key="index.info" />


html>
--------------------------------------

Next copy struts-blank.war to f:\tomcat41\webapps and start the tomcat with JAVA_HOME as jdk1.4. A folder named struts-blank will be created. Rename the folder as localedemo. Copy the above JSP file to f:\tomcat41\webapps\localedemo.

Now we have to edit the property files for various locales. The struts framework(struts1.1) provides a property file named application.properties. It is present in the folder f:\tomcat41\webapps\localedemo\web-inf\classes\resources. We have to add our own property file in this folder only. Our property file much be named along with the language code

For example the language code of
1. German - de
2. Spanish - es
3. English - en
4. Korean - ko
5. French - fr
6. Italy - it

So, when we write i18n message in German language it must be placed in property file named application_de.properties and all the properties files must be present in the resources folder only. Also when we write the property file of a particular language it need not be of the same language. For example we can create application_de.properties and write the message in french or english. In fact, the message does not depend on any language. It is a simple key value pair. The message we give for the key is just substituted. The property file to locate the value of key depends on the language settings of the browser. For this example, we will write four properties file as follows.

f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_de.properties

index.info=GERMANY
---------------------------------------------------------
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_es.properties

index.info=SPAIN
-----------------------------------------------------------
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_en.properties

index.info=ENGLISH
-----------------------------------------------------------
f:\tomcat41\webapps\localedemo\web-inf\classes\resources\ application_fr.properties

index.info=FRANCE
------------------------------------------------------------
Also append this text in the application.properties file
index.info=STRUTS TUTORIAL.

Now we have to add entry in the
struts-config.xml file for all the properties files. The entry and its corresponding portion is shown below.



resources.application_fr"/>
resources.application_es"/>
resources.application_en"/>
resources.application_de"/>
resources.application"/>

Now restart the Tomcat server. Open the Internet Explorer and type the URL as http://localhost:8080/localedemo/localedemo.jsp. We will get the message 'ENGLAND'. This is because our default browser language is 'United States English'.

Now we have to change the language settings of the browser to change the locale. For that, Open a new Internet Explorer, goto 'Tools' menu and select the 'Internet Options'. In the 'Internet Option' dialog box, select 'General' tab and click the 'Languages...' button. We will get 'Language Preference' dialog box. There click 'Add...' button and add the languages. For this example add English, Spanish, German and French. Here we have languages specific to particular region. For example we have, French Belgium, French Canada, French France etc., we can select any one of these in all cases. Next select 'German' and by using the 'Move up' button, place it on the top. Now type the URL as http://localhost:8080/localedemo/localedemo.jsp. We will get the message 'GERMAN' Similarly place 'Spanish' and 'French' at the top, we will get the message 'SPAIN' and 'FRANCE' respectively.
read more “STRUTS INTERNATIONALIZATION”

Configuring Struts DataSource Manager on Tomcat 5

This tutorial shows you how you can configure Struts DataSource Manager on the Tomcat 5.5.9 server. We will use struts 1.2.7 in this tutorial. In this tutorial we will configure Struts DataSource Manager to use MySQL Database and use the connection provided by Struts DataSource in action class.

Downloading and Installing Tomcat 5.5.9
Download jakarta-tomcat-5.5.9 from http://jakarta.apache.org/tomcat/. Install it on your machine. Run and test the pages that comes with the tomcat.

Download Struts
Download Struts struts-1.2.7 from http://struts.apache.org/download.cgi and unzip it to your favorite directory. Go to the struts-1.2.7\webapps directory and then unzip struts-blank.war file. We will use this file to write our tutorial.

Download MySQL JDBC Driver
Download mysql-connector-java-3.0.16-ga-bin.jar from here mysql-connector-java-3.0.16-ga-bin.jar or you can download and use the latest version of mysql jdbc driver. Copy the JDBC driver file (mysql-connector-java-3.0.16-ga-bin.jar or latest version) to the jakarta-tomcat-5.5.9\common\lib directory of your tomcat installation. This will add the MySQL JDBC driver to the tomcat server.

Creating MySQL Database
In this tutorial I am using MySQL server installed on my local machine. You can download and install MySQL on your local machine and use for this tutorial. If you already have MySQL server then you can use the existing MySQL server.

Create database "strutsdatabase" on the MySQL server and then run the following query to create test table.

CREATE TABLE `test` (
`username` varchar(20) NOT NULL default ''
) TYPE=MyISAM;

/*Data for the table `test` */

insert into `test` values ('rajesh'),('George'),('Vikas'),('Prakash'),('Mahesh');

Above query creates test table and then populates the table with data.

Configuring Struts Application
Now create a directory "strutsdatabase" in the jakarta-tomcat-5.5.9\webapps\ directory and copy the content of struts-blank application (unzipped above) in the strutsdatabase directory.

Now start the tomcat and try to access the strutsdatabase application by typing the url http://localhost:8080/strutsdatabase in browser. Your browser should display the welcome page. After testing shutdown the tomcat server.

Configuring Struts DataSource Manager
The Struts DataSource manager makes it easy for your Action class get the database connection. To configure the Stuts DataSource Manager we will uncomment the entry in the struts-config.xml.

Uncomment and then entry in the struts-config.xml and then change the line "org.apache.commons.dbcp.BasicDataSource" to "org.apache.tomcat.dbcp.dbcp.BasicDataSource". In tomcat 5.5.9 dbcp classes are packaged in naming-factory-dbcp.jar archieve, so we are using "org.apache.tomcat.dbcp.dbcp.BasicDataSource" instead of "org.apache.commons.dbcp.BasicDataSource". After this change the database dirver, database url and passwor in the tag.

You element should look like:



org.apache.tomcat.
dbcp.dbcp.BasicDataSource">
property="driverClassName"
value="com.mysql.jdbc.Driver" />
property="url"
value="jdbc:mysql://localhost:3306
/strutsdatabase?autoReconnect=true" />
property="username"
value="root" />
property="password"
value="" />
property="maxActive"
value="10" />
property="maxWait"
value="5000" />
property="defaultAutoCommit"
value="false" />
property="defaultReadOnly"
value="false" />
property="validationQuery"
value="SELECT COUNT(*) FROM test" />


Create action Class to Test the DataSource
Now we will write the code of Action class for getting the connection form DataSource:

package test;

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

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

import java.sql.*;

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

javax.sql.DataSource dataSource;
java.sql.Connection myConnection=null;
try {
dataSource = getDataSource(request);
myConnection = dataSource.getConnection();
Statement stmt=myConnection.createStatement();
ResultSet rst=stmt.executeQuery("select

username from test");
System.out.println("*************

*****************************");
System.out.println("********Out

Put from TestDataSource ******");
while(rst.next()){
System.out.println("User Name is:

" + rst.getString("username"));
}
System.out.println("************

******************************");
rst.close();
stmt.close();
// do what you wish with myConnection
} catch (SQLException sqle) {
getServlet().log("Connection.process", sqle);
} finally {
//enclose this in a finally block to make
//sure the connection is closed
try {
myConnection.close();
} catch (SQLException e) {
getServlet().log("Connection.close", e);
}
}


return mapping.findForward("success");
}
}

Following code is used to get the data source and then connection from Struts DataSource:

dataSource = getDataSource(request);
myConnection = dataSource.getConnection();

Save this file(TestDataSource.java) into jakarta-tomcat-5.5.9\webapps\strutsdatabase\WEB-INF\src\java\test directory. Add the servlet API into class path. Then open dos prompt and navigate to jakarta-tomcat-5.5.9\webapps\strutsdatabase\WEB-INF\src\ directory and issue run ant. This will compile the action class (TestDataSource.java) and copy it to the classes directory of the webapplication.

Creating Action Mapping struts-config.xml
Now add the following action mapping into the struts-config.xml:

path="/DataSource"
type="test.TestDataSource">

Running and testing
Start tomcat and browse the url http://localhost:8080/strutsdatabase/DataSource.do. Your browser should show the following output.

Now check tomcat console, it should display records fetched from database.

You can download my struts-config.xml from here.

Note: The DataSource manager is being retained in Struts 1.x for backward compatibility but may not be retained in Struts 2.x or later.

read more “Configuring Struts DataSource Manager on Tomcat 5”

Set the action name

2. Set the action name to the action attribute of html:link

// eventdispatchaction.jsp

Create an Employee record

3. Either directly use the method name to call as a query string parameter, or use an alias.





// eventdispatchaction.jsp ( Direct calling )



Update Employee details





// eventdispatchaction.jsp ( Calling using an alias )



Create an Employee record

What are the advantages?

  1. Events can be attached to controls directly.

  2. No need to use a separate hidden variable or a query string for mapping the method name to the actual method to call.

  3. Actual method to call can be aliased with a pseudo name.

What are the disadvantages?

  1. The need to extend the class from EventDispatchAction and hence cannot extend our class from a custom base class.

EventActionDispatcher

How to create one?

  1. Extend your action from Action, similar to the case in ActionDispatcher. This is what is desirable for us.

// CRUDEventActionDispatcher.java

/**

* This is an example class for demonstrating EventActionDispatcher

* functionality. Observe here that we can also extend our class from

* BaseAction class like in ActionDispatcher example and move our

* session validation to that class.

*



* The EventActionDispatcher as the name suggests is used to attach

* events to the html controls. This type of aggregation eliminates the

* need to define a parameter(eg., methodToCall). We havent used any

* hidden parameters to combine an event to a method. This event-to-method

* mapping is removed using EventActionDispatcher.

*

* We can also use an Alias for the method name and map it to the method name

* as can be seen in the createAlias event.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDEventActionDispatcher extends Action {

protected ActionDispatcher dispatcher = new EventActionDispatcher(this);

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response) throws Exception {

// This method will handle the dispatching of the action to the appropriate method.

System.out.println("I am in CRUDEventActionDispatcher - execute");

return dispatcher.execute(mapping, form, request, response);

}

...

}

2. Set the action name to the action attribute of html:link.





// eventactiondispatcher.jsp



Create an Employee record

3. Either directly use the method name to call as a query string parameter, or use an alias.





// eventactiondispatcher.jsp ( Direct calling )



Delete Employee record






// eventactiondispatcher.jsp ( Calling using an alias )



Create an Employee record

What are the advantages?

  1. Events can be attached to controls directly.

  2. No need to use a separate hidden variable or a query string for mapping the method name to the actual method to call.

  3. Actual method to call can be aliased with a pseudo name.

What are the disadvantages?

1. None.

Note that the use of true (read=true) while using the query string variable to specify the event name is optional. Also, note that this variable is different from the one we used earlier (methodToCall). Here we directly specify the event name or its alias not the variable name or the actual method to call.

Assumptions

  1. It is assumed that you have the complete source code of this discussion with you.

  2. For some examples, I assume that our application is a full fledged web application wherein a user is authenticated before entry into the system and we are validating the user session in a base class. Why is this so important? Because, to use some types of aggregations, we should extend our action class from a specific subclass of Action. This restricts us from extending the action class from a custom base class. DispatchAction is an example of such an action.

  3. It is assumed that all we are interested in are the Create, Read, Update and Delete operations on an entity in the database. These
    actions, also called CRUD actions, are the basis for all the examples of this discussion.

  4. One more assumption is that it is assumed that we are interested in attaching events to the HTML controls, which you may be familiar in JSF, where in we attach events to the controls using action and actionListener attributes.

  5. It is assumed that the examples provided depict only one way of usage. You are free to experiment with the code, like for instance, replacing query string with hidden variables.

Source Code

Download

read more “Set the action name”

Set the mapping name

3. Set the mapping name to the action attribute of html:link





























// mappingdispatchaction.jsp



Create an Employee record



Read an Employee details



Update Employee details



Delete Employee record

What are the advantages?

  1. Single action class can be used for multiple action mappings. The attribute of the action mapping can be added or removed and a new mapping can be created while the action class remains the same.
  2. Useful in places where there are 2 actions, one of which needs a formbean while the other does not but both uses the same Action class. In such cases, two new action mappings can be created one with ‘name' attribute and one without and the same Action class name can be used.

What are the disadvantages?

  1. We still cannot extend our CRUDMappingDispatchAction from any custom base class and have the aggregation intact.
  2. Cannot attach events. More about this later.

ActionDispatcher

How to create one?

1. Extend your action class from Action. Do not confuse about the inclusion of BaseAction.java. I have just moved the common code part to this BaseAction and extended my action class from it.

// src/CRUDActionDispatcher.java

/**

* This is an example class for demonstrating ActionDispatcher

* functionality. Observe here that we are extending our

* action class from BaseAction where the session validation

* is done.

*



* See BaseAction for more details

*



* If we use any other aggregating action then we cannot

* use session validation as we cannot extend our custom class

* (BaseAction in this case). This is the biggest strength of ActionDispatcher

* type of aggregation and the biggest weakness of all other types.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDActionDispatcher extends BaseAction {

public ActionForward create(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

// Code for Create Employee follows

System.out.println("I am in CRUDActionDispatcher - create");

return ( mapping.findForward("success") );

}

...

}

// src/BaseAction.java

/**

* This is an example class where session validation

* is done normally. But if you look at closely we have

* actually written our ActionDispatcher code here and

* simply extended our example class for demonstrating

* ActionDispatcher functionality from this class.

*



* This is the place where every time the session is

* checked. A sample code snippet could be :

*

*

* session = request.getSession(false); // which returns the existing session

* if( session != null ) {

* // allow the user in

* } else {

* // throw him/her out to the relogin page

* }

*


*



* This is perhaps the most crucial part of any web application

* since this is to be done for every class or every class is to be

* extended from this kind of (Base) class.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public class BaseAction extends Action {

protected ActionDispatcher dispatcher =

new ActionDispatcher(this, ActionDispatcher.DEFAULT_FLAVOR);

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

// This is a default method and is mandatory since we are

// not extending any dispatcher action class(eg, extends ActionDispatcher{ }).

// This method will handle the dispatching of the action to the appropriate method.

// Code for Session Validation follows

System.out.println("I am in BaseAction - execute");

return dispatcher.execute(mapping, form, request, response);

}

}

2. Declare a variable of type ActionDispatcher as follow (see above code snippet):

protected ActionDispatcher dispatcher = new ActionDispatcher(this, ActionDispatcher.DEFAULT_FLAVOR);

3. Add the following line as the last line of your default ‘execute' method. Note that this is not needed for other methods. (see above code snippet)

return dispatcher.execute(mapping, form, request, response);

4. Define a query string parameter or a hidden variable (‘methodToCall' in our examples)






// actiondispatcher.jsp



Create an Employee record

5. Set the parameter's value to the desired function name of the action class (create, read etc).






// actiondispatcher.jsp





// actiondispatcher.jsp



Create an Employee record



Create an Employee record

What are the advantages?

  1. Observe that we have extended our action class (CRUDActionDispatcher) from our custom base class (BaseClass) which is what we wanted in order to decouple the session validation code into the BaseClass.
  2. Only a couple of changes to the code avoid the need to extend from a subclass.
  3. Easy to use.

What are the disadvantages?

  1. We cannot attach events to the controls.

Event Aggregating Actions

If you are familiar with swing programming you might have heard of events. An event is nothing but a piece of code that is executed when, say, a button is clicked, a linked is clicked etc. In all the above types of actions we have defined a parameter (methodToCall) which is in turn mapped to the action name. This is a good feature for security concerns. However, we need a way to have the method name different from the actual method called, at the same time eliminating the need to define a hidden variable or a query string. This is where the Event Aggregating Actions comes into the picture.

There are two important types of Event Aggregating Actions as said earlier, namely, EventDispatchAction and EventActionDispatcher

Let's see each one of them in detail.

EventDispatchAction

How to create one?

1. Extend your action from EventDispatchAction

// CRUDEventDispatchAction.java

/**

* This is an example class for demonstrating EventDispatchAction

* functionality. Observe here that we can also extend our class from

* BaseAction class like in ActionDispatcher example and move our

* session validation to that class.

*



* The EventActionDispatcher as the name suggests is used to attach

* events to the html controls. This type of aggregation eliminates the

* need to define a parameter(eg., methodToCall). We havent used any

* hidden parameters to combine an event to a method. This event-to-method

* mapping is removed using EventActionDispatcher.

*

* We can also use an Alias for the method name and map it to the method name

* as can be seen in the createAlias event.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDEventDispatchAction extends EventDispatchAction {

public ActionForward create(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response) throws Exception {

// Code for Create Employee follows

System.out.println("I am in CRUDEventDispatchAction - create");

return ( mapping.findForward("success") );

}

...

}

read more “Set the mapping name”

Aggregating Actions In Struts Revisited

In my previous article Aggregating Actions in Struts , I have given a brief idea of how to create action aggregations. An action aggregation is a grouping of a set of related actions into a single unified action in order to eliminate the need to write a new action class for every action. In this part, I will walk through a full-fledged practical example of each of the types presented in Part I namely the DispatchAction , LookupDispatchAction , MappingDispatchAction and ActionDispatcher along with two new aggregations which slightly differ in syntax but are more efficient than the previous ones. These are EventDispatchAction and EventActionDispatcher . I call these new actions as УEvent Aggregating ActionsФ and the ones in Part I as УNon-Event Aggregating Actions.Ф

Now let's go into some details.

Non-Event Aggregating Actions


DispatchAction

How to create one?

ХаExtend your action class from DispatchAction.
// src/CRUDDispatchAction.java

/**

* This is an example class for demonstrating DispatchAction

* functionality. Observe here that we are extending our

* action class not from Action but from DispatchAction.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDDispatchAction extends DispatchAction {

public ActionForward create(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

// Code for Create Employee follows

System.out.println("I am in CRUDDispatchAction - create");

return ( mapping.findForward("success") );

}

...

}

ХаDefine a query string parameter or a hidden variable (СmethodToCall' in our examples)






// dispatchaction.jsp



Create an Employee record

Ð¥ Set the parameter's value to the desired function name of the action class (create, read etc).





// dispatchaction.jsp



Create an Employee record

What are the advantages?

  1. If you observed carefully, we have created only one action class (CRUDDispatchAction) instead of four different classes for each of the Create, Read, Update and Delete actions. This is why aggregating actions are for.
  2. Easy to use.
  3. Cleaner code syntax.

What are the disadvantages?

  1. We cannot extend our CRUDDispatchAction from any custom base class and still have the aggregation.
  2. Observe that we have used html:link in dispatchaction.jsp and a query string variable appended to the URL. So, the method name is visible in the URL. In order to avoid this, we need to set it using javascript.
  3. Cannot attach events. More about this later.

LookupDispatchAction

How to create one?

1. Extend your action class from LookupDispatchAction .

// src/CRUDLookupDispatchAction.java

/**

* This is an example class for demonstrating CRUDLookupDispatchAction

* functionality. Observe here that we are extending our

* action class not from Action but from LookupDispatchAction.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDLookupDispatchAction extends LookupDispatchAction {

protected Map getKeyMethodMap() {

Map map = new HashMap();

map.put("button.create", "create");

map.put("button.read", "read");

map.put("button.update", "update");

map.put("button.delete", "delete");

return map;

}

public ActionForward create(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

// Code for Create Employee follows

System.out.println("I am in CRUDLookupDispatchAction - create");

return ( mapping.findForward("success") );

}

...

}

2. Write an html:form and change the action name to the desired action mapping name.

// lookupdispatchaction.jsp



...

3. Set the Сproperty' attribute of the submit button to parameter name which should hold the method name to call.






// lookupdispatchaction.jsp





What are the advantages?

  1. Multiple submit buttons within the same form only differing in their name.
  2. The actual method to call is mapped in the action class.
  3. Button names can be set in a properties file.

What are the disadvantages?

  1. We cannot extend our CRUDLookupDispatchAction from any custom base class and still have the aggregation.
  2. Change to the button name requires JVM restart.
  3. Extra overhead of creating a separate method for button-to-method name mapping.(getKeyMethodMap() in our example)
  4. Cannot attach events. More about this later.

MappingDispatchAction

How to create one?

1. Extend your action class from MappingDispatchAction

// src/CRUDMappingDispatchAction.java

/**

* This is an example class for demonstrating MappingDispatchAction

* functionality. Observe here that we are extending our

* action class not from Action but from MappingDispatchAction.

*

* @author Praveen Babu Kusuma

* @version 1.0.0

*

* http://www.javahome.co.nr

* http://praveen.awardspace.com

*/

public final class CRUDMappingDispatchAction extends MappingDispatchAction {

public ActionForward create(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

// Code for Create Employee follows

System.out.println("I am in CRUDMappingDispatchAction - create");

return ( mapping.findForward("success") );

}

...

}

Define different mappings for each action as needed.

// struts-config.xml






type="com.CRUDMappingDispatchAction"

scope="request"

parameter="create"

>








type="com.CRUDMappingDispatchAction"

scope="session"

parameter="read"

>








type="com.CRUDMappingDispatchAction"

scope="request"

input="/mappingdispatchaction.jsp"

parameter="update"

>








type="com.CRUDMappingDispatchAction"

scope="request"

name="employeeForm"

parameter="delete"

validate="false"

>






read more “Aggregating Actions In Struts Revisited”

STRUTS ACTION - AGGREGATING ACTIONS IN STRUTS

If you are a Struts developer then you might have experienced the pain of writing huge number of Action classes for your project. The latest version of struts provides classes using which you can aggregate a related set of actions into a single unified action. In this article we will see how to achieve this. Struts provides four important classes for this purpose. These classes are called as Dispatchers. The important Dispatchers that struts provides includes : DispatchAction, ActionDispatcher , LookupDispatchAction and MappingDispatchAction.

All these classes can be found in the package org.apache.struts.actions. Let us look in to each of these in detail. Our examples use the simple CRUD actions.

DispatchAction: In this type of aggregation, the action class must extend DispatchAction class as shown.


public final class CRUDDispatchAction extends DispatchAction {

public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward("success"));
}
...


and the action mapping will be as





in your jsp you can call this action as

Create
...


Observe that the above class extends DispatchAction and so you cannot use this method if your class already extends your (some) super class (eg., the class where the session is validated/invalidated). Here the user has to send a query string variable (methodToCall) to set the action name to call.

ActionDispatcher: This flavor of aggregation is same as DispatchAction except that we need not extend ActionDispatcher, so we can use this method even if our class extends a super class. The following code snippet shows this scenario.


public final class CRUDActionDispatcher extends Action {

protected ActionDispatcher dispatcher = new ActionDispatcher(this, ActionDispatcher.DEFAULT_FLAVOR);

public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return dispatcher.execute(mapping, form, request, response);
}

The DEFAULT_FLAVOR field suggests that the default parameter is "method" if none is specified as parameter in struts-config.xml (eg,. methodToCall).
ActionDispatcher flavor also needs methodToCall parameter to be set (using hidden variable or a query string) as in case of DispatchAction.

LookupDispatchAction: This type of aggregation is useful in situations where in you have multiple submit buttons in a single form. The class must extend LookupDispatchAction. However, the great thing about this type is that its java script free. That means, you need not set any hidden variables or pass query string however, you must use submit buttons as shown.



...
The example Action class will be as follows

public class CRUDLookUpDispatchAction extends LookupDispatchAction {

protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("button.create", "create");

return map;
}
public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward("success"));
}
Observe the getKeyMethodMap() method. The submit button names are specified in a Map and their keys comes from MessageResources file. Struts picks up the name from this file and redirects it to the value specified in the Map. The calling code in jsp however has multiple submit buttons only differing in their names.

MappingDispatchAction: This aggregation extends MappingDispatchAction class. This is the most useful type among the four types available. But as seen in other cases, you can use this type only when your action does not extend any other action. The good thing about this type is that the action mappings can differ and so need not be the same as in all other cases. To illustrate this consider the below mappings.








Notice that in the first action mapping, there is no form bean while in the second the bean name is specified. This means that the user has the flexibility to change the mapping according to his needs and hence not been contained to use a constant mapping for all the CRUD actions. Note that in all the other types of aggregations, we must use the same mapping for all the CRUD actions.

Conclusion: Each of these types has their own pros and cons. DispatchAction is the default type which uses java script and we must extend DispatchAction to use it, ActionDispatcher is same as DispathAction except that we do not extend any action , LookupDispatchAction gives the flexibility to use multiple submit buttons while MappingDispatchAction allows us to change the action mappings according to our need. So each one of these has a particular usage and which one to use depends on the user requirement.
read more “STRUTS ACTION - AGGREGATING ACTIONS IN STRUTS”

Struts MappingDispatchAction Example

Struts MappingDispatch Action (org.apache.struts.actions.MappingDispatchAction) is one of the Built-in Actions provided along with the struts framework.

The org.apache.struts.actions.MappingDispatchAction class is a subclass of org.apache.struts.actions.DispatchAction class. This class enables a user to collect related functions into a single action class. It needs to create multiple independent actions for each function. Here in this example you will learn more about Struts MappingDispatchAction that will help you to grasp the concept better.

Let's develop a class MappingDispatch_Action which is a sub class of org.apache.struts.actions.MappingDispatchAction class. This class does not provide an implementation for the execute() method because DispatchAction class itself implements this method.

MappingDispatchAction class is much like the DispatchAction class except that it uses a unique action corresponding to a new request , to dispatch the methods . At run time, this class manages to delegate the request to one of the methods of the derived Action class. Selection of a method depends on the value of the parameter passed from the incoming request. MappingDispatchAction uses this request parameter value and selects a corresponding action from the different action-mappings defined. This eliminates the need of creating an instance of ActionForm class.

MappingDispatch_Action class contains multiple methods ie.. add() , edit() , search() , save() . Here all the methods are taking the same input parameters but each method returns a different ActionForward like "add" in case of add() method , "edit" in case of edit() etc. Each ActionForward is defined in the struts-config.xml file (action mapping is shown later in this page).


Developing an Action Class (MappingDispatch_Action.java)

package roseindia.net;

/**
* @author Amit Gupta
* @Web http://www.roseindia.net
* @Email struts@roseindia.net
**/

import java.io.*;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.apache.struts.actions.MappingDispatchAction;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class MappingDispatch_Action extends MappingDispatchAction
{


public ActionForward add(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
System.out.println("You are in add function.");
return mapping.findForward("add");
}

public ActionForward edit(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
System.out.println("You are in edit function.");
return mapping.findForward("edit");
}

public ActionForward search(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
System.out.println("You are in search function");
return mapping.findForward("search");
}

public ActionForward save(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
System.out.println("You are in save function");
return mapping.findForward("save");
}






}

No need to Develop an ActionForm Class

Developing the Action Mapping in the struts-config.xml

Here, we need to create multiple independent actions for each method defined in the action class. Note that the value specified with the
parameter attribute is used to delegate request to the required method of the MappingDispatch_Action Class.

type="roseindia.net.MappingDispatch_Action"
parameter="add"
input="/pages/MappingDispatchAction.jsp"
scope="request"
validate="false">



type="roseindia.net.MappingDispatch_Action"
parameter="edit"
input="/pages/MappingDispatchAction.jsp"
scope="request"
validate="false">




type="roseindia.net.MappingDispatch_Action"
parameter="search"
input="/pages/MappingDispatchAction.jsp"
scope="request"
validate="false">




type="roseindia.net.MappingDispatch_Action"
parameter="save"
input="/pages/MappingDispatchAction.jsp"
scope="request"
validate="false">





Developing jsp page

Code of the jsp (MappingDispatchAction.jsp) to delegate requests to different jsp pages :

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>


Mapping Dispatch Action Example


Dispatch Action Example


Call Add Section


Call Edit Section


Call Search Section


Call Save Section




Add the following line in the index.jsp to call the form.


  • Struts File Upload


    Example demonstrates how MappingDispatchAction class works.

  • Building and Testing the Example

    To build and deploy the application go to Struts\Strutstutorial directory and type ant on the command prompt. This will deploy the application. Open the browser and navigate to the MappingDispatchAction.jsp page. Your browser displays the following MappingDispatchAction page.

    Selecting Call Add Section displays the following MappingDispatchActionAdd.jsp page

    Selecting Call Edit Section displays the following MappingDispatchActionEdit.jsp page

    Selecting Call Search Section displays the following MappingDispatchActionSearch.jsp page

    Selecting Call Save Section displays the following MappingDispatchActionSave.jsp page

    read more “Struts MappingDispatchAction Example”

    Struts LookupDispatchAction Example

    Struts LookupDispatch Action (org.apache.struts.actions.LookupDispatchAction) is one of the Built-in Actions provided along with the struts framework.

    .The org.apache.struts.actions.LookupDispatchAction class.is a subclass of org.apache.struts.actions.DispatchAction class.This class enables a user to collect related functions into a single action class. It eliminates the need of creating multiple independent actions for each function. Here in this example you will learn more about Struts LookupDispatchAction that will help you to grasp the concept better.

    Let's develop a class LookupDispatch_Action which is a sub class of org.apache.struts.actions.LookupDispatchAction class. This class does not provide an implementation for the execute() method because DispatchAction class itself implements this method.

    LookupDispatchAction class is much like the DispatchAction class except that it uses a Java Map and ApplicationResource.properties file to dispatch methods . At run time, this class manages to delegate the request to one of the methods of the derived Action class. Selection of a method depends on the value of the parameter passed from the incoming request. LookupDispatchAction uses this parameter value to reverse-map to a property in the Struts Resource bundle file (ie..ApplicationResource.properties). This eliminates the need of creating an instance of ActionForm class.

    LookupDispatch_Action class contains multiple methods ie.. add() , edit() , search() , save() . Here all the methods are taking the same input parameters but each method returns a different ActionForward like "add" in case of add() method , "edit" in case of edit() etc. Each ActionForward is defined in the struts-config.xml file (action mapping is shown later in this page).

    Notice the implementation of the getKeyMethodMap()method.This method is required to map the names of the keys in the Struts Resource bundle file (ie..ApplicationResource.properties) to the methods in the class. The key values in the bundle file are matched against the value of the incoming request parameter ( which is specified in the action tag through struts-config.xml file). Then this matching key is mapped to the appropriate method to execute ,the mecahanism is implemented through the getKeyMethodMap()and can be defined as key-to-method mapping.

    Here is the code for Action Class

    package roseindia.net;

    /**
    * @author Amit Gupta
    * @Web http://www.roseindia.net
    * @Email struts@roseindia.net
    **/

    import java.io.*;
    import java.util.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.ServletException;
    import org.apache.struts.actions.LookupDispatchAction;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;

    public class LookupDispatch_Action extends LookupDispatchAction
    {
    protected Map getKeyMethodMap(){
    Map map = new HashMap();
    map.put("roseindia.net.add","add");
    map.put("roseindia.net.edit","edit");
    map.put("roseindia.net.search","search");
    map.put("roseindia.net.save","save");
    return map;
    }


    public ActionForward add(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response) throws Exception{
    System.out.println("You are in add function.");
    return mapping.findForward("add");
    }

    public ActionForward edit(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response) throws Exception{
    System.out.println("You are in edit function.");
    return mapping.findForward("edit");
    }

    public ActionForward search(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response) throws Exception{
    System.out.println("You are in search function");
    return mapping.findForward("search");
    }

    public ActionForward save(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response) throws Exception{
    System.out.println("You are in save function");
    return mapping.findForward("save");
    }
    }

    No need to Develop an ActionForm Class

    Instead create an Application Resource Property File:

    Application.properties
    in the same directory structure where classes are saved.

    roseindia.net.add=add
    roseindia.net.edit=edit
    roseindia.net.search=search
    roseindia.net.save=save

    Add the following, Message Resources Definitions in struts-config.xml

    Develop the following Action Mapping in the struts-config.xml

    Here, Action mapping helps to select the method from the Action class for specific requests. Note that the value specified with the parameter
    attribute is used to delegate request to the required method of the LookupDispatch_Action Class.

    path="/LookupDispatchAction"
    type="roseindia.net.LookupDispatch_Action"
    parameter="parameter"
    input="/pages/LookupDispatchAction.jsp"
    name="LookupDispatchActionForm"
    scope="request"
    validate="false">




    Developing jsp page

    Code of the jsp (LookupDispatchAction.jsp) to delegate requests to different jsp pages :

    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
    <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>


    Dispatch Action Example


    Dispatch Action Example


    Call Add Section


    Call Edit Section


    Call Search Section


    Call Save Section



    Add the following line in the index.jsp to call the form.


  • Struts File Upload


    Example demonstrates how LookupDispatchAction class works.
  • Building and Testing the Example

    To build and deploy the application go to Struts\Strutstutorial directory and type ant on the command prompt. This will deploy the application. Open the browser and navigate to the LookupDispatchAction.jsp page. Your browser displays the following LookupDispatchAction page.

    Selecting Call Add Section displays the following LookupDispatchActionAdd.jsp page

    Selecting Call Edit Section displays the following LookupDispatchActionEdit.jsp page

    Selecting Call Search Section displays the following LookupDispatchActionSearch.jsp page

    Selecting Call Save Section displays the following LookupDispatchActionSave.jsp page

    read more “Struts LookupDispatchAction Example”