You are on page 1of 38

Asking is Good, so keep it up!!!

Struts
1. Introduction
There is a big difference between a school page and a professionally developed Web site. The page designer (or
HTML developer) must understand colors, the customer, product flow, page layout, browser compatibility,
image creation, JavaScript, and more. Putting a great looking site together takes a lot of work, and most Java
developers are more interested in creating a great looking object interface than a user interface. Java Server
Pages (JSP) technology provides the glue between the page designer and the Java developer.

If you have worked on a large-scale Web application, you understand the term change. Model-View-Controller
(MVC) is an approach put together to help control change. MVC decouples interface from business logic and
data. Struts is an MVC2 implementation that uses Servlets and JSP tags, from the J2EE specifications, as part
of the implementation.

Model-View-Controller (MVC)
MVC helps resolve some of the issues with the single module approach by dividing the problem into three
categories:

• Model
The model contains the core of the application's functionality. The model encapsulates the state of the
application.
• View
The view provides the presentation of the model. It is the look of the application. The view can access
the model getters, but it has no knowledge of the setters. In addition, it knows nothing about the
controller. The view should be notified when changes to the model occur.
• Controller
The controller reacts to the user input. It creates and sets the model.

MVC Model 1

The Model 1 architecture is very simple. A request is made to a JSP or servlet and then that JSP or servlet
handles all responsibilities for the request, including processing the request, validating data, handling the
business logic, and generating a response.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


1
Asking is Good, so keep it up!!!

Consequences of the single-page approach

• Heavy HTML and Java coupling


The coder of the JSP file must be both a page designer and a Java developer. The result is often either
terrible Java code or an ugly page, or sometimes both.
• Java and JavaScript blur
As the pages become larger, there can be a tendency to implement some JavaScript. When the
JavaScript appears in a page, the script can get confused with the Java code. An example of a possible
point of confusion is using client-side JavaScript to validate the email field.
• Embedded flow logic
To understand the entire flow of the application, you have to navigate all of the pages. Imagine the
spaghetti logic on a 100-page Web site.
• Debugging difficulties
In addition to being ugly to look at, HTML tags, Java code, and JavaScript code all in one page makes it
difficult to debug problems.
• Tight coupling
Changes to business logic or data means possibly touching every page involved.
• Aesthetics
Visually, in large pages, this type of coding looks messy.

JSP Tags: No more Java code in my HTML

A JSP tag is simply a way of abstracting out code from a JSP file.

JSP tags solved only part of our above listed problems. We still have issues with validation, flow control, and
updating the state of the application. This is where MVC2 comes to the rescue.

MVC Model 2

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


2
Asking is Good, so keep it up!!!

In this MVC architecture, a central servlet, known as the Controller, receives all requests for the application.
The Controller then processes the request and works with the Model to prepare any data needed by the View
(which is usually a JSP) and forwards the data to a JSP. The JSP then uses the data prepared by the Controller to
generate a response to the browser. In this architecture, the business and presentation logic are separated from
each other. Having the separation of business and presentation code accommodates multiple interfaces to the
application, be they Web, wireless, or GUI (Swing). Additionally, this separation provides excellent reuse of
code.

Note – Model 1 (single page approach) and Model 2 (true MVC approach), so don’t be confuse if you asked for
MVC model 1, you need to explain single page approach.

2. Struts Framework
What a framework means?
• an extensible/generic/flexible architecture following set of standards and patterns
• Focuses on a specific domain (web / j2ee applications etc)
• Provides extension points
• Can be customized and used on projects

What is Struts Framework?


• Provide APIs those are used to create web applications
• Uses Java Beans, Java Servlets, and Java Server pages (JSP)
• Based on the MVC design pattern
• Rich set of tag libraries provided for presentation tier
• Extensible

(one time) digest struts-config.xml


[configuration file]

1.1 get mapping


Action Mapping

Action Servlet and


RequestProcessor Action
1 event 2 dispatch [Business
[Controller] Logic]
HTTP Request
1.2 create 2.1 (can) use

Action Form

Client
Browser
2.4 use 2.3 create
3 forward Action Forward 2.2 interact

JSP
3.1 (can) interact Application
[View]
4 update State
[Model]
HTTP Response

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


3
Asking is Good, so keep it up!!!

Struts API Zoo

• Most of the times we will extend ActionForm for making input page form beans and Action class for
putting the business logic like we did in servlet.
• We can customize controller parts also.
• Most of the API and tags works in internationalized fashion, so they will take data to display as a key
and we will define these key-values into properties file. So by default our application will be
multilingual.
• We can define our validation rules on user inputs into xml, means highly configurable and reusable
validation code.
• We can break our look and feel into tiles and each tile can be configured through xml, means making the
presentation configurable.
• We define the flow inside the struts-config.xml that makes our application flow highly configurable.

So waiting for what this is the right time to write HelloWorld…..

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


4
Asking is Good, so keep it up!!!

3. HelloWorld Setup

Folder Structure

//hello.jsp
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>

<html>
<head><title>Struts HelloWorld</title></head>

<body>
<html:errors/>
<h1>Struts HelloWorld</h1>
<html:form action="/hello.do">
<bean:message key="hello.msg.label" />
<html:text property="msg" />
<html:submit />
</html:form>
</body>
</html>

//success.jsp
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>

<html>
<head><title>Struts HelloWorld Success
Page</title></head>

<body>
<h1>Struts HelloWorld Success Page</h1>
<bean:write name="message" />
</body>
</html>

//Message.properties
hello.msg.label=Message :
errors.msg.empty=Empty Message Not Allowed.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


5
Asking is Good, so keep it up!!!

// HelloAction.java
package org.test;

import javax.servlet.http.*;
import org.apache.struts.action.*;

public class HelloAction extends Action {


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

HelloForm hf = (HelloForm) form;

String msg = hf.getMsg();


request.setAttribute("message", "Your Message " + msg + " received!!!");

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

//HelloForm.java
package org.test;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.*;

public class HelloForm extends ActionForm {

private String msg;

public String getMsg() {


return msg;
}

public void setMsg(String msg) {


this.msg = msg;
}

public ActionErrors validate(ActionMapping mapping,


HttpServletRequest request) {

ActionErrors errors = new ActionErrors();


if (msg != null && msg.length() == 0) {
// add the error message
errors.add("HelloForm", new ActionMessage("errors.msg.empty"));
}
return errors;
}
}

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


6
Asking is Good, so keep it up!!!

//struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC


"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">

<struts-config>

<!--Form Bean Definitions -->


<form-beans>
<form-bean name="helloForm" type="org.test.HelloForm" />
</form-beans>

<!--Action Mapping Definitions -->


<action-mappings>
<action path="/welcome" forward="/hello.jsp" />

<action path="/hello" type="org.test.HelloAction"


input="/hello.jsp" name="helloForm" validate="true">
<forward name="success" path="/success.jsp"></forward>
</action>
</action-mappings>

<!--Controller Configuration -->


<controller
processorClass="org.apache.struts.action.RequestProcessor" />

<!--Message Resources Definitions -->


<message-resources parameter="Message" />

</struts-config>

//web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/tlds/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/tlds/struts-html.tld</taglib-location>
</taglib>
</web-app>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


7
Asking is Good, so keep it up!!!

For accessing the application type following URL in your browser


http://localhost:8080/hello/welcome.do

1. Since the request ends at .do so the ActionServlet will get called. This servlet works as Front
Controller.
2. ActionServlet will take out /welcome from /welcome.do and look for mapping
3. it will found direct forward rule and will forward the request to /hello.jsp
4. when you submit the hello.jsp page in action it calls /hello.do
5. again step 1 and 2 will be repeated
6. Now this time it founds an action class and form associated with this action.
7. instantiate the form bean object, called the setter method for properties name matched and then called
the validate method which returns ActionErrors object
8. it check this object if empty then execution goes to HelloAction execute() method else it forward the
request to input="/hello.jsp"
9. in execute we cast the form, fetch the value and then added into request
request.setAttribute("message", "Your Message " + msg + " received!!!");
execute() returns ActionForward that hold the logical name of the page to be forwarded.
<forward name="success" path="/success.jsp"></forward>
And finally we see the success.jsp as a final output.

Hurray we did it….

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


8
Asking is Good, so keep it up!!!

See this Sequence Diagram for more insight -

Controller: ActionServlet Model: Action, Business Layer View: JSPs

Note – Actions are part of model or controller is somewhat debatable but if we look into the functionality of
Action, it is used for get/set data from beans, ejbs or database and provides this data to view for
representation. In this sense it is perfect to say actions are part of model.
But if we say Servlets are replaced by Action and Servlets in struts are used for controlling then Action
seems to the part of controller. But the first discussion is having more weightage.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


9
Asking is Good, so keep it up!!!

Struts Components we used so far –


• Action Servlet – Front Controller
• struts-config.xml – flow configuration
• Action Mapping – keep the action related configuration
• Action Form – form bean
• Action Class – business logic starting point
• Action Forward – keep the logical name of the resource to which request will be forwarded.
• Action Errors, Action Message - <html:errors/> reads all these action messages for display
• Resource Bundle (Message.properties) – makes our application Multilingual.
• Struts Tag Library tags <bean:write>, <bean:message>, <html:errors>, <html:form>,
<html:submit>, <html:text>

Struts Application - Simple 5 Step Process –


• Create and edit the web app deployment descriptor (web.xml)
• Create and edit the struts-config.xml file with appropriate action and form mapping.
• Write a Java class extending Struts Action class.
• Provide the business functionality in the ‘execute ()’ method.
• Write a JavaBean class extending Struts ActionForm class
• Write the HTML based view elements in a JSP.

Big Note –
• Only one instance of your Action class is created and used for all requests.
• Thus they need to be thread safe
• Exceptions thrown from execute() method should be appropriately logged
• Consider using custom actions to simplify coding

Action Purpose Action Class


Bridge Actions Integrate Struts with other servlets ForwardAction
IncludeAction
Base Actions Extend your functionality DispatchAction
LookupDispatchAction
SwitchAction

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


10
Asking is Good, so keep it up!!!

4. Internationalization
In above example we used Message.properties that keeps the text values to display on pages and thats why we
used <bean:message key=”hello.msg.label”/> in our jsp.

For different countries language support, we have to create multiple properties file that follow some naming
convention and that is Message_xx.properties. Where xx is the two letter language code.
Step 1 - create a property file for Japanese (language code - ja)
//Message_ja.properties
hello.msg.label=ergtmlkr :
errors.msg.empty=em45549jogfkg knkld 9-9.

Step 2 – add the Japanese language in browser and move it up also.

Step 3 – refresh the application and see now the value is coming from ja properties file automatically.

I know you will not believe how easy it is to make multilingual application in struts, but it is the fact. This is
one of the benefits of using struts tags, they are language sensitive.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


11
Asking is Good, so keep it up!!!

5. Standard Struts Actions

5.1 ForwardAction

This is provided as a simple utility action that can be used for scenarios in which you simply want to link to a
JSP page. Of course, linking directly to the JSP would be a violation of the MVC principles because all requests
are supposed to be routed through the Controller. ForwardAction can be used to create links to JSPs so that
you don’t have to create an action whose only responsibility is to forward a request every time you want to link
to a JSP. With ForwardAction, you simply create an action mapping in the Struts configuration file and specify
the location to which the action will forward.

The ForwardAction creates a request dispatcher and forwards control to a context-relative URI supplied by
the ActionMapping. The context-relative path is given as the ActionMapping’s parameter property:
<action-mappings>
<action path="/welcome"
type="org.apache.struts.actions.ForwardAction"
parameter="/hello.jsp/>
</action-mappings>

The practical upshot is that instead of http://localhost:8080/hello/hello.jsp appearing on the browser’s address
bar, where it could be bookmarked for direct access, the Action URI appears instead:
http://localhost:8080/hello/welcome.do

There is an another way to achieve this, we have used this approach


<action path="/welcome" forward="/hello.jsp" />

In this case RequestProcessor’s processForward()/processInclude() method handle this and dispatch the request
to target resource defined in forward/include attribute of action mapping.

5.2 Include Action

This action behaves similarly to ForwardAction, but instead of forwarding to the specified URL, the specified
URL is included. This action is useful when you want to include the contents of one page in another.

In servlet we have already discussed RequestDispatcher forward() and include(). Forward


and IncludeAction doing the same.

<action-mappings>
<action path="/welcome"
type="org.apache.struts.actions.IncludeAction"
parameter="/hello.jsp/>
</action-mappings>

Note -

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


12
Asking is Good, so keep it up!!!

5.3 Dispatch Action


A common strategy among Struts developers is to use the same Action class to handle several related tasks and
thus eliminates the need to create separate, independent actions for each function. For example, A good
example is performing the basic CRUD (Create Read Update Delete) operations on a user data record. Instead
of creating an CreateUserAction class, ReadUserAction, UpdateUserAction class, and a DeleteUserAction
class, by extending DispatchAction, you can create one UserAction class that has four methods: create( ),
read( ), update() and delete( ). At run time, DispatchAction manages routing requests to the appropriate
method in its subclass. DispatchAction determines which method to call based on the value of a request
parameter that is passed to it from the incoming request. It uses reflection to replace the fragile if/then logic
most developers would use instead.

Three things that you have to consider –


1. Extends your Action class with DispatchAction
public class UserAction extends DispatchAction{
}

2. Each of the dispatch methods must use the same signature as the usual Action execute () method.

public ActionForward create(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response)throws
IOException,ServletException;

3. In action mapping define the name of a request parameter, which value will be the method name and it
will be used to select the method. We have to set the value as a hidden parameter or form element or
through java script. Any how the value of the parameter must be there in request.
<action path="/user" type="org.test.UserAction" name="userForm"
scope="request" input="/user.jsp" parameter="method">
<forward name="success" path="/user.jsp"></forward>
</action>

Note – “method” is the name of parameter which will have value create/read/update/delete or
anything match to your method name.
/**************UserAction.java***********************************
public class UserAction extends DispatchAction {

public ActionForward create(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Create Method");
return mapping.findForward("success");
}
public ActionForward read(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Read Method");
return mapping.findForward("success");
}
public ActionForward update(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Update Method");
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
13
Asking is Good, so keep it up!!!

return mapping.findForward("success");
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Delete Method");
return mapping.findForward("success");
}
}

Note – if errors related to form beans then add


<form-bean name="userForm" type="org.test.UserForm" /> and create a UserForm.java

To select the create method, you could call http://localhost/hello/user.do?method=create


To select the read method, you could call http://localhost/hello/user.do?method=read
To select the update method, you could call http://localhost/hello/user.do?method=update
To select the delete method, you could call http://localhost/hello/user.do?method=delete

Or create a user.jsp like this in which buttons name is “method” and value is method
name.
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<html:form action="/user.do">
<html:submit property="method">
<bean:message key="button.add" />
</html:submit>
<html:submit property="method">
<bean:message key="button.view" />
</html:submit>
<html:submit property="method">
<bean:message key="button.update" />
</html:submit>
<html:submit property="method">
<bean:message key="button.delete" />
</html:submit>
</html:form>

Simple view source version of user.jsp


<form name="userForm" method="post" action="/hello/user.do">
<input type="submit" name="method" value="create">
<input type="submit" name="method" value="read">
<input type="submit" name="method" value="update">
<input type="submit" name="method" value="delete">
</form>

Click the individual button and see the output message in tomcat-

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


14
Asking is Good, so keep it up!!!

5.4 LookupDispatchAction
A convenient way to select a dispatch method is by linking it with a button, as we did in above example. This
can be problematic in a localized application, since the label of the button may change according to the user’s
locale. For one user, the button may read Delete; for another, it may read Borre.

The LookupDispatchAction solves this problem by mapping the labels back to their original message key. The
key can then be mapped to the appropriate dispatch method. Since the message key may not be an appropriate
name for a Java method, the developer provides a hash table that maps the message keys to the dispatch method
names:

public class LookupUserAction extends LookupDispatchAction {

protected Map getKeyMethodMap() {


Map map = new HashMap();
map.put("button.add", "create");
map.put("button.view", "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 IOException, ServletException {
System.out.println("USer Action : Create Method");
return mapping.findForward("success");
}
public ActionForward read(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Read Method");
return mapping.findForward("success");
}
public ActionForward update(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Update Method");
return mapping.findForward("success");
}
public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
System.out.println("USer Action : Delete Method");
return mapping.findForward("success");
}
}

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


15
Asking is Good, so keep it up!!!

5.5 Switch Action and Struts Modules


All Struts applications have at least one module. Some applications may be configured to use multiple modules.
Each module has its own set of configuration files and presentation pages and can be developed as if it were the
only module in the application.
Of course, at some point the modules need to interact if they are going to work as a single application.
SwitchAction (org.apache.struts.actions.SwitchAction) is a standard Action that can switch to another module
and then forward control to a path within that module.

<action-mappings>
<action path="/switch" type="org.apache.struts.actions.SwitchAction"/>
</action-mappings>

Once configured in the Struts configuration file, SwitchAction can be put to use. Simply create a link to the
action and specify the module to switch to and a page to forward to afterward. The module to switch to is
specified with the prefix parameter and the page to forward to afterward is specified with the page parameter.
The following URL illustrates how to use the request parameters:

http://localhost:8080/hello/switch.do?prefix=/dg&page=/discussion.do

This example URL switches to the /dg module, and the /discussion.do page will be forwarded to after the
module has been switched.

Struts Modules

Situation – Suppose our portal has three modules, one is default and other two are dg (discussion group) and
news (news group). All the modules are running independently, means having the separate web folder structure
in web server.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


16
Asking is Good, so keep it up!!!

Now we want to merge dg and news with default and want to make one application. So we have to take care of
following things.

1. Single web.xml with other module name and configuration filename information inside this.
2. Whenever forwarding request from one module to other module use one of the approach.
• use the org.apache.struts.actions.SwitchAction
• use a <forward> (global or local) and specify the contextRelative attribute with a value of true,
• can specify the "module" parameter as part of any of the Struts JSP hyperlink tags (Include, Img,
Link, Rewrite, or Forward).

So, your main web.xml file will look like this

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>config/dg</param-name>
<param-value>/WEB-INF/struts-config-dg.xml</param-value>
</init-param>
<init-param>
<param-name>config/news</param-name>
<param-value>/WEB-INF/struts-config-news.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<?xml version="1.0" encoding="ISO-8859-1" ?>

*************************struts-config-dg.xml ************************
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<!--Action Mapping Definitions -->
<action-mappings>
<action path="/dg" forward="/dg.jsp" />
</action-mappings>

<!--Controller Configuration -->


<controller
processorClass="org.apache.struts.action.RequestProcessor" />

<!--Message Resources Definitions -->


<message-resources parameter="dg" />
</struts-config>
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
17
Asking is Good, so keep it up!!!

*************************struts-config-news.xml ************************
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<!--Action Mapping Definitions -->
<action-mappings>
<action path="/news" forward="/news.jsp" />
</action-mappings>

<!--Controller Configuration -->


<controller
processorClass="org.apache.struts.action.RequestProcessor" />

<!--Message Resources Definitions -->


<message-resources parameter="news" />
</struts-config>

Note – you have to copy all the .class and properties files used in module in main WEB-
INF classes folder. You can keep the following type of files in module specific folders
like xmls, images, jsps etc.

*************************dg.jsp************************
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<h1>Discussion group</h1>
<bean:message key="dg.msg"/>

*************************dg.properties************************
dg.msg=Hello DG Module

*************************news.properties************************
dg.msg=Hello News Module

*********************hello.jsp of default module *********************


<html>
<head><title>Struts HelloWorld</title></head>
<body>
<h1>Struts HelloWorld</h1>

1.<a href="/hello/dg/dg.jsp">Direct JSP Access Of DG Module Current Module is


Default</a><br>
2.<a href="/hello/dg/dg.do">Action Through Controller</a><br>
3.<a href="/hello/switch.do?prefix=/dg&page=/dg.jsp">Switch Action</a>

</body>
</html>

1. Will Not work – not going through controller, and we have used <bean:message> tag
that will try to pick key value from property file but from which module?? Yes,
from default because we are making direct access to jsp so not going through
controller, so module specific things will not be applicable.
2. will work – going through controller
3. will work – providing information to controller, it require to configure
SwitchAction

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


18
Asking is Good, so keep it up!!!

Note – you can put your dg and news folder inside WEB-INF that stop direct access.
What you have to do in path attribute you have to provide value “/WEB-INF/dg.jsp” instead
of “/dg.jsp”

After merging the folder will look like this.

//hello.jsp of default module want to move on dg


module, when you will be using struts tags they are
module sensitive by default

<html:link action="/dg/dg.do">Test 1</html:link>


<html:link action="/dg/dg.jsp">Test 2</html:link>
<html:link module="/dg" action="/dg.jsp">Test 3
</html:link>

See the view source of the page it will be-

<a href="/hello/dg/dg.do"> Test 1</a>


<a href="/hello/dg/dg.do"> Test 2</a>
<a href="/hello/dg/dg.do"> Test 3</a>

Surprised!!!! All will work, you know why, because all request
are going through controller.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


19
Asking is Good, so keep it up!!!

6. struts-config.xml

We have seen <action-mappings>, <form-beans>, <controller> and <message-resources> now time to


look these configuration elements in more detail –

6.1 <global-forwards> if there is global forward then might be something like <local-forward> should also
exist?? Yes, in <action> we used <forward> that was the local forward.

If a logical name used by Action not found locally then it looks inside the <global-forwards> entries.

So <global-forwards> encapsulates a set of forwards, defined by forward tags, which are global to the
application.

<global-forwards>
<forward name="success" path="/success.jsp"/>
<forward name="failure" path="/failure.jsp"/>
</global-forwards>

Local Forward –
<action-mappings>
<action path="/hello" type="org.test.HelloAction" name="helloForm"
scope="request" validate="true" input="/hello.jsp">
<forward name=”success” path=”/hello.jsp”/>
</action-mappings>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


20
Asking is Good, so keep it up!!!

6.2 <global-exceptions>

The global-exceptions tag is used to encapsulate a set of exception handlers, defined by exception tags, which
are global to the application. This set of global exception handlers will be used to handle any exceptions being
thrown from actions and that action mappings does not have matching local exception tag.

<global-exceptions>
<exception type="org.test.exception.DataNotFoundException"
key="errors.data.notfound"
path="/error.jsp"/>
</global-exceptions>

Local Exception Handling -


<action-mappings>
<action path="/hello"
type="org.test.HelloAction"
name="helloForm"
scope="request"
validate="true"
input="/hello.jsp">
<exception type="org.test.exception.DataNotFoundException"
key="errors.data.notfound" path="/error.jsp"/>
<forward name=”success” path=”/hello.jsp”/>
</action>
</action-mappings>

Example – follow these steps for global exception handling in struts

1. Create an application exception class.


2. Update HelloAction to throw an application exception.
3. Set up an exception handler in the struts-config.xml file.
4. Create an exception-handler JSP.
5. Add an exception error message to the Message.properties file.
6. Recompile, repackage, and run the updated application.

The following sections walk through each step of the process in detail.

1. Create an application exception class.

package org.test.exception;
public class NoDataFoundException extends Exception {
}

2. Update HelloAction to throw an application exception


package org.test;

import java.sql.ResultSet;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.test.exception.NoDataFoundException;

public class HelloAction extends Action {


public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
21
Asking is Good, so keep it up!!!

throws Exception {

ResultSet rs = null;
if (rs == null)
throw new NoDataFoundException();
return mapping.findForward("success");

}
}

3. Set up an exception handler in the struts-config.xml file.

<action path="/hello" type="org.test.HelloAction"


input="/hello.jsp" name="helloForm" validate="true">
<exception type="org.test.exception.NoDataFoundException"
key="errors.data.notfound" path="/error.jsp"/>
<forward name="success" path="/success.jsp"></forward>
</action>

4. Create an exception-handler JSP, error.jsp


<%@ taglib uri="/tags/struts-html" prefix="html"%>
<html>
<head><title>Hello Struts</title></head>
<body>
<font size="+1">Hello Struts</font>
<br>
<hr width="100%" noshade="true">
<html:errors />
</body>
</html>

5. Add an exception error message to the Message.properties file.

####error.jsp
errors.data.notfound=Data Not Found

6. Run the application after restart

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


22
Asking is Good, so keep it up!!!

6.3 <plug-in>

Defines a plugin that Struts loads at application startup and unloads at application shutdown.

Each plugin class must implement Struts’ org.apache.struts.action.PlugIn interface. Upon application
startup, the plugin’s init( ) method will be called. Upon application shutdown, the plugin’s destroy( )
method will be called

<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml"/>
<set-property property="moduleAware" value="true"/>
</plug-in>

At run time, when Struts parses a configuration file with a definition similar to this, it will use reflection to
look up and invoke the setDefinitionsConfig( ) and setModuleAware( ) methods of the class specified by
the plug-in tag’s className attribute, passing them the defined values.
Step 1 – write a class that implements PlugIn interface
package org.test.plugin;

import javax.servlet.ServletException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;

public class TestPlugin implements PlugIn {

String name = null;

public void init(ActionServlet arg0, ModuleConfig arg1)


throws ServletException {
System.out.println("Plugin Init Called : "+name);
}
public void destroy() {
System.out.println("Destroy Called");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Step 2 – make a entry in struts-config.xml
<plug-in className="org.test.plugin.TestPlugin">
<set-property property="name" value="sumit agarwal" />
</plug-in>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


23
Asking is Good, so keep it up!!!

6.4 <data-sources>

As a rule, you should always use a connection pool to access a database. The DataSource interface is the
preferred way to implement a connection pool today. Many containers and database systems now bundle a
DataSource implmentation that you can use. Most often, the DataSource is made available through JNDI. The
JNDI approach makes it easy for your business classes to access the DataSource without worrying about who
set it up.

It is preferred that data connectivity be handled directly by the business classes,


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

<data-sources>
<data-source
type="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<set-property property="url"
value="jdbc:mysql://127.0.0.1:3306/student" />
<set-property property="user" value="root" />
<set-property property="password" value="root" />
<set-property property="maxCount" value="5" />
<set-property property="driverClass"
value="com.mysql.jdbc.Driver" />
<set-property property="minCount" value="1" />
</data-source>
</data-sources>

public class DatabaseAction extends Action {

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

DataSource ds = getDataSource(request);
Connection conn = ds.getConnection();
if (conn != null) {
// access the database
System.out.println("we got the connection and class is "
+ conn.getClass().getName());
}

return mapping.findForward("success");

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


24
Asking is Good, so keep it up!!!

6.5 <form-beans>

<form-beans>
<form-bean name="helloForm" type="org.test.HelloForm" />
<form-bean name="userForm" type="org.test.UserForm" />
</form-beans>

When HTML forms are submitted to a Struts application, Struts takes the incoming form data and uses it to
populate the form’s corresponding Form Bean. The Struts Controller layer then uses the Form Beans to access
data that must be sent to the Model layer. On the flip side, the Controller layer populates Form Beans with
Model layer data so that it can be displayed with the View layer. Essentially, Form Beans are simple data
containers. They either contain data from an HTML form that is headed to the Model via the Controller or
contain data from the Model headed to the View via the Controller.

We have to do following things for creating a form bean

1. extend form bean class with ActionForm


2. declare properties with the same name as defined in html/jsp page
3. provide getter/setter method for these properties by following Java Bean naming conventions
4. can also override validate(), reset() method, called bean hooks.

In hello.jsp we used <html:form> tag in which action /hello is associated with hello form bean because it
provides name=”helloForm” attribute in struts-config.xml.
<html:form action="/hello.do">
<bean:message key="hello.msg.label" />
<html:text property="msg" />
<br/>
<html:checkbox property="override">Do you want to override the default
message!!!</html:checkbox>
<br/>
<html:submit />
</html:form>

When this page rendered either through controller (http://localhost:8080/hello/welcome.do) or directly


http://localhost:8080/hello/hello.jsp, A HelloForm Bean object will get created with properties having
default values, then reset() hook will get called.

public class HelloForm extends ActionForm {

private String msg = "hello";


private boolean override = true;

public ActionErrors validate(ActionMapping mapping,


HttpServletRequest request) {

ActionErrors errors = new ActionErrors();

if (override) {
System.out.println("I have deselected the checkbox but still this if
block is running");
}
if (msg != null && msg.length() == 0) {
// add the error message
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
25
Asking is Good, so keep it up!!!

errors.add("HelloForm", new ActionMessage("errors.msg.empty"));


}
return errors;
}

public void reset(ActionMapping mapping, HttpServletRequest request) {

System.out.println("reset get called just before populating the values


into/from request");

msg = "hello world";


// override = false;
}

public boolean isOverride() {


return override;
}
public void setOverride(boolean override) {
this.override = override;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

When hello.jsp page will be rendered it will look like this

Now deselect the checkbox and press submit button and see the message on tomcat screen

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


26
Asking is Good, so keep it up!!!

First reset message appears because when form bean is created, resetted then putted into hello.jsp, second reset
message appears when we clicked submit button, /hello.do action will get called (associated form bean is
created then resetted then populated with the alues given by user). But I have deselected the checkbox then how
if (override) {
System.out.println("I have deselected the checkbox but still this if block is
running");
}
block is executing?

Note - Browsers send the value of a check box only if it is checked when the HTML form is submitted so
nothing is sent for override property field, so no setter get called and if setter will not called then what will be
the default value of property override? Exactly wilt which you have initialized and that is
private boolean override = true;

So now you know why the above if() get executed. What to do for overcome with this problem? Yes override
the reset method because it will executed before populating the value from request and irrespective of what are
the values are coming into request.
public void reset(ActionMapping mapping, HttpServletRequest request) {

System.out.println("reset get called just before populating the values


into/from request");

msg = "hello world";


// override = false;
}

So uncomment this override = false; the if block will not get executed.

validate() hook is get called if in action mappings we have given validate=”true”

<action path="/hello" type="org.test.HelloAction"


input="/hello.jsp"
name="helloForm" validate="true" scope=”request”>
<forward name="success" path="/success.jsp" />
</action>

Here we perform the validation of the values provided by user as an input. You will be
wondering why such validation we are doing again, if we have already done this in
javascript? Think, if javascript was disabled in browser.

In validate we prepare error messages then put into ActionErrors, if ActionErrors is not
blank then controller forward us to resource given in input="/hello.jsp" otherwise
Action’s execute will get called.

Note - If you do not want to call validate() now then you can set validate="false” and
later in action we can call form.validate() any time.

An another benefit of the reset( ) method hook is that it offers a convenient place to reset data between requests
when using Form Beans that are stored in session scope. When Form Beans are stored in session scope, they
persist across multiple requests. This solution is most often used for wizard-style process flows. Sometimes it’s
necessary to reset data between requests, and the reset( ) method provides a convenient hook for doing this.

We can change the form bean scope in action mapping configuration scope=”session”

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


27
Asking is Good, so keep it up!!!

7. DynaActionForm

Dynamic Form Beans are an extension of Form Beans that allows you to specify their properties inside the
Struts configuration file instead of having to create a concrete class, with a getter and setter method for each
property. The concept of Dynamic Form Beans originated because many developers found it tedious to create
for every page a Form Bean that had a getter and setter method for each of the fields on the page’s HTML form.
Using Dynamic Form Beans allows the properties to be specified in a Struts configuration file. To change a
property, simply update the configuration file. No code has to be recompiled.

The following snippet illustrates how Dynamic Form Beans are configured in the Struts configuration file:

<!-- Form Beans Configuration -->


<form-beans>
<form-bean name="userForm" 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="department" type="java.lang.String"/>
</form-bean>
</form-beans>

Dynamic Form Beans are declared in the same way as standard Form Beans, by using the form-bean tag. The
difference is that the type of the Form Bean specified with the form-bean tag’s type attribute must be
org.apache.struts.action.DynaActionForm or a subclass thereof. Additionally, the properties for Dynamic
Form Beans are specified by nesting form-property tags beneath the form-bean tag. Each property specifies
its name and class type. Additionally, an initial value for the property can be specified using the form-property
tag’s initial attribute, as shown next:

<form-property name="department" type="java.lang.String" initial="MCA"/>

If an initial value is not supplied for a property, Struts sets the initial value using Java’s initialization
conventions. That is, numbers are set to zero and objects are set to null.

Because you declare Dynamic Form Beans in the Struts configuration file instead of creating concrete classes
that extend ActionForm, you do not define reset( ) or validate( ) methods for the Dynamic Form Beans. The
reset( ) method is no longer necessary for setting default values because the initial attribute on the form-
property tag achieves the same effect. The DynaActionForm class’s implementation of the reset( ) method
resets all properties to their initial value when it is called. You can either code the functionality of the validate(
) method inside action classes or use the Validator framework for validation. These two options eliminate the
need to create a validate( ) method on the Form Bean. If, however, you have a special case where you need to
have an implementation of the reset( ) and/or validate( ) method for your Dynamic Form Bean, you can
subclass DynaActionForm and create the methods there. Simply specify your DynaActionForm subclass as
the type of the Form Bean in the Struts configuration file to use it.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


28
Asking is Good, so keep it up!!!

8. Validator Framework

The Validator framework is set up as a pluggable system of validation routines that can be applied to Form
Beans. Each validation routine is simply a Java method that is responsible for performing a specific type of
validation and can either pass or fail. By default, Validator comes packaged with several useful validation
routines that will satisfy most validation scenarios. However, if you need a validation that is not provided by the
framework, you can create your own custom validation routine and plug it into the framework.

So by using this you make your validations configurable. Let’s see by an example.

Step 1 – configure Validator plug-in in 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 2 – create a form bean class that will extend from ValidatorForm instead of ActionForm.

package org.test;
import org.apache.struts.validator.ValidatorForm;

public class LoginForm extends ValidatorForm {


private String username;
private String password;

public String getUsername() {


return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

Step 3 - You configure this Form Bean in the struts-config.xml file the same way you would a regular Form
Bean, as shown here:

<form-beans> <form-bean name="loginForm" type="org.test.LoginForm"/> </form-beans>

Note – if you do not want to create a form bean class specially then you can use DynaValidatorForm.
<form-beans>
<form-bean name="loginForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="username" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
</form-bean>
</form-beans>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


29
Asking is Good, so keep it up!!!

Step 4 – edit sample validation.xml

<form name="loginForm">
<field property="username" depends="required">
<arg key="loginForm.username" />
</field>
<field property="password" depends="required,mask">
<arg key="Password" resource=”false”/>  no property file will be used
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value>
</var>
</field>
</form>

Based on the type of Form Bean being validated, Validator will attempt to match the name either against a Form
Bean's logical name or against an action's path. Inside the <form> element, <field> elements are used to define
the validations that will be applied to specified Form Bean fields. The <field> element's property attribute
corresponds to the name of a field in the specified Form Bean. The depends attribute specifies the logical
names of validation routines from the validator-rules.xml file that should be applied to the field. The
validations specified with the depends attribute will be performed in the order specified and they all must pass.

Step 5 – put error messages key-value in Message.properties


# Error messages for Validator framework validations, copied from validation-ruls.xml
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.

Notice that each message has placeholders in the form of {0}, {1}, or {2}. At run time, the placeholders will be
substituted for another value such as the name of the field being validated. This feature is especially useful in
allowing you to create generic validation error messages that can be reused for several different fields of the
same type.

errors.required={0} is required.

When you use the required validation in the validation.xml file, you have to define the value that should be
used to substitute {0} in the error message:

<form name="auctionForm">
<field property="bid" depends="required">
<arg0 key="prompt.bid"/>
</field>
</form>
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
30
Asking is Good, so keep it up!!!

Press the submit button without providing any value-

8.1 ValdatorActionForm and DynaValidatorActionForm

When using ValidatorForm or DynaValidatorForm based Form Beans, Validator uses the logical name for
the Form Bean from the struts-config.xml file to map the Form Bean to validation definitions in the
validation.xml file. This mechanism is ideal for most cases; however, there are scenarios where Form Beans
are shared among multiple actions. One action may use all the Form Bean's fields and another action may use
only a subset of the fields. Because validation definitions are tied to the Form Bean, the action that uses only a
subset of the fields has no way of bypassing validations for the unused fields. When the Form Bean is validated,
it will generate error messages for the unused fields because Validator has no way of knowing not to validate
the unused fields; it simply sees them as missing or invalid.

To solve this problem, Validator provides two additional ActionForm subclasses that allow you to tie
validations to actions instead of Form Beans. That way you can specify which validations to apply to the Form
Bean based on which action is using the Form Bean. For concrete Form Beans, you subclass
org.apache.struts.validator.ValidatorActionForm, as shown here:

public class AddressForm extends ValidatorActionForm {



}

For Dynamic Form Beans, you specify a type of org.apache.struts.validator.DynaValidatorActionForm for


your Form Bean definition in the struts-config.xml file:

<form-bean name="addressForm"
type="org.apache.struts.validator.DynaValidatorActionForm">

</form-bean>

Inside your validation.xml file, you map a set of validations to an action path instead of a Form Bean name,
because if you have two actions defined, Create Address and Edit Address, which use the same Form Bean, as
shown here, each has a unique action path:

<action-mappings>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


31
Asking is Good, so keep it up!!!

<action path="/createAddress"
type="com.jamesholmes.minihr.CreateAddressAction"
name="addressForm"/>
<action path="/editAddress"
type="com.jamesholmes.minihr.EditAddressAction"
name="addressForm"/>
</action-mappings>

The following validation.xml file snippet shows two sets of validations that are intended for the same Form
Bean, but are distinguished by different action paths:

<formset>
<form name="/createAddress">
<field property="city" depends="required">
<arg0 key="prompt.city"/>
</field>
</form>
<form name="/editAddress">
<field property="state" depends="required">
<arg0 key="prompt.state"/>
</field>
</form>
</formset>

Because your Form Bean subclasses either ValidatorActionForm or DynaValidatorActionForm, Validator


knows to use an action path to find validations instead of the Form Bean's logical name.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


32
Asking is Good, so keep it up!!!

9 Struts Tiles

Tiles allows you to exploit the concept of JSP includes by providing a framework for defining and dynamically
populating page layouts.

Each page layout is simply a JSP that defines a template frame (or outline) with placeholders for where content
should go. At run time, Tiles replaces the placeholders with their associated content, creating a complete page
and unique instance of the layout. To accomplish this, Tiles uses its concepts of definitions and attributes

header.jsp
layout.jsp

body.jsp

menu.jsp

footer.jsp

A Tiles definition creates a piece of content that Tiles can insert into a JSP using that definition’s name. Each
definition consists of a name (or identifier), a layout JSP, and a set of attributes associated with the definition.
Once defined, a definition can be included in a page or, as is most often the case, be used as the target of Struts
forward. In both cases, when the definition is encountered, Tiles passes to the layout JSP specified by the
definition the set of attributes that were declared for that definition. An attribute value can be the path to a JSP,
a literal string, or a list of either.

To facilitate the use of definitions and attributes, Tiles uses an XML configuration file (tiles-defs.xml) for
storing their definitions. Tiles also provide a JSP tag library for defining definitions and attributes. Additionally,
the Tiles Tag Library is used for inserting attributes into JSPs.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


33
Asking is Good, so keep it up!!!

Using Tiles - Using the Tiles framework involves these five steps:

1. Enable the Tiles plugin.


2. Create Tiles definitions.
3. Create layout JSPs and use the Tiles Tag Library.
4. Create content JSPs to fill in the layout JSPs
5. Using Tiles definitions.

1. Enable the Tiles plugin - make an entry in struts-config.xml

<!-- Tiles Configuration -->


<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config"
value="/WEB-INF/tiles-defs.xml"/>
</plug-in>

2. Create Tiles definitions.

The first, and most often used, way that you can define Tiles definitions and attributes is by placing them in an
XML configuration file named tiles-defs.xml.

XML Configuration File-Based Definitions and Attributes


<?xml version="1.0"?>

<!DOCTYPE tiles-definitions PUBLIC


"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">

<tiles-definitions>
<definition name="search.page" path="/mainLayout.jsp">
<put name="header" value="/header.jsp"/>
<put name="body" value="/search.jsp"/>
<put name="footer" value="/footer.jsp" />
</definition>
</tiles-definitions>

Each definition in the tiles-defs.xml file has its own definition that is declared with a definition tag. The
definition tag assigns a logical name to the definition, with the name attribute, and specifies the path to a layout
JSP for the definition, with the path attribute. The logical name given to the definition will be used to refer to
the definition inside JSPs and the Struts configuration file. Nested inside the definition tag, put tags are used to
specify the definition's list of attributes.

JSP-Based Definitions and Attributes


The second way that you can define a Tiles definition and its attributes is by specifying them with Tiles Tag
Library tags inside JSPs. Following is a basic definition defined in a JSP:
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>

<tiles:definition id="search.page" template="/mainLayout.jsp" >


<tiles:put name="header" value="/header.jsp" />
<tiles:put name="body" value="/search.jsp" />
<tiles:put name="footer" value="/footer.jsp" />
</tiles:definition>

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


34
Asking is Good, so keep it up!!!

This definition will be stored in a page scope JSP variable named search.page (as specified by the id attribute
of the definition tag) so that it can be accessed from other tags. To use this JSP-based definition, you must use
Tiles' insert tag, as shown next:

<tiles:insert beanName="search.page" flush="true"/>

Extending Definitions

This functionality is similar to the way inheritance works in Java. When defining a definition, you can specify
that the definition extends another definition, instead of specifying a layout JSP for the definition.

<tiles-definitions>

<!-- Main Layout -->


<definition name="main.layout" path="/mainLayout.jsp">
<put name="title" value=""/>
<put name="header" value="/header.jsp"/>
<put name="menu" value="/menu.jsp"/>
<put name="body" value=""/>
<put name="footer" value="/footer.jsp" />
</definition>

<!-- Search Page -->


<definition name="search.page" extends="main.layout">
<put name="title" value="Search Page"/>
<put name="body" value="/search.jsp"/>
</definition>

<!-- Employee Layout -->


<definition name="employee.layout" extends="main.layout">
<put name="menu" value="/employee/menu.jsp"/>
</definition>

<!-- Employee Edit Page -->


<definition name="employeeEdit.page" extends="employee.layout">
<put name="title" value="Employee Edit Page"/>
<put name="body" value="/employee/edit.jsp"/>
</definition>

</tiles-definitions>

3. Create layout JSP

//mainLayout.jsp

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

<html>
<head>
<title><tiles:getAsString name="title"/></title>
</head>
<body>

<tiles:insert attribute="header"/>

<table>
Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com
35
Asking is Good, so keep it up!!!

<tr>
<td width="20%"><tiles:insert attribute="menu"/></td>
<td width="80%"><tiles:insert attribute="body"/></td>
</tr>
</table>

<tiles:insert attribute="footer"/>

</body>
</html>

At run time, when a definition uses this layout, it will make a set of attributes available to the page to be
inserted with the Tiles Tag Library's insert tag.

4. Create content JSPs

Content JSPs are used to fill in the placeholders created by layouts. These JSPs simply contain the HTML
necessary to fill in a specific section of a layout. You create these JSPs the same way you would create JSPs
that are used for includes. You don't, however, specifically source in any of these JSPs into the layout JSPs, as
you would if you were using includes. Instead, layout JSPs use Tiles tags to insert attributes whose values point
to these content JSPs.

5. Using Tiles definitions.

Once you have created Tiles layout JSPs and have defined definitions that use them, you can put the definitions
to use. There are two different ways to use definitions:

1. you can insert the definition's content into a JSP, or


2. You can use definitions as the targets of Struts forwards.

The following example illustrates how to insert a Tiles definition into a JSP:

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

<html>
<head><title>Employee Search</title></head><body>

<font size="+1">Hello Tiles</font><br>


<hr width="100%" noshade="true">
<tiles:insert definition="search.page"/>
<hr width="100%" noshade="true">
</body>
</html>

Most ofenly you will use Second Approach,


<global-forwards>
<forward name="search" path="search.page"/>
</global-forwards>

Notice that the path attribute specifies the name of a Tiles definition. The Tiles request processor will recognize
this and handle processing for this forward. Similarly, for local forwards you can use tiles definition name.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


36
Asking is Good, so keep it up!!!

10. Struts wildcard mapping

We can reduce the number of action mappings by combining similar action mappings into a single generic
mapping.

many applications use standard conventions for naming action paths, Action classes, and ActionForms, making
their application easier to organize and maintain. Struts 1.2 allows you to leverage these conventions in your
struts-config.xml file. Create your action elements using an asterisk (*) as a wildcard in the path attribute. When
Struts finds the action mapping for a given request path, it attempts to find an exact match. If an exact match is
not found, it attempts a match using the wildcards.

<action path="/Edit*" type="org.test.Edit{1}Action" name="{1}Form" scope="request">


<forward name="success" path="/edit_{1}.jsp"/>
</action>

Now if we use some conventions for naming action paths, Action classes, and ActionForms then we do not
require to create seprate mapping for /EditStudent, /EditVendor, /EditProject etc. * will be matched to Student,
Vendor, Project and {1} will be replaced with this matched value. What we need to care the files with matching
names must exist.

The action element attributes that can use wildcard-matched strings via the {n} notation are the following:

• type
• name
• roles
• parameter
• attribute
• forward
• include
• input

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


37
Asking is Good, so keep it up!!!

11 Struts Token

You need to stop users from inadvertently submitting a form twice Use the Struts token facility to reject a
duplicate request.

It is very easy to use -

1. Before you load the JavaServer Pages (JSP) page that has the html:form tag on it, call saveToken inside
an action.
2. When the user submits the form, call isTokenValid and handle the form only if the token is valid.

public class SaveTokenAction extends Action {


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

// save a token
saveToken(request);

// load the data to view


BusinessService.loadData( );

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

public class CheckTokenAction extends Action {


public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (isTokenValid(request)) {
// reset the token
resetToken(request);

// save data
BusinessService.saveData( );
}
else {
ActionErrors errors = new ActionErrors( );
errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("Invalid token"));
saveErrors(request, errors);
return mapping.getInputForward();
}
return mapping.findForward("success");
}
}
Trick - When the form is rendered on the JSP page, Struts generates an HTML hidden field containing the
token value. You can generate the token value as request parameter on a hyperlink by setting
transaction=true on the html:link tag. The token value, whether rendered as a hidden field or a request
parameter, is only generated if a token is found in the current request for the JSP.

Sumit Agarwal (MCA Gold Medalist), mail me at jexperts@gmail.com


38

You might also like