Struts Framework – Using Custom Class as Struts Action Controller

**adsense_4x1Block**
Introduction:



In this struts framework tutorial we will customize default Struts Action’s configuration so that it will use our custom java class to process the request and then navigate user back to appropriate page.


Along the way, we will also set folder structure of basic Struts Project so that it can be extended for larger complex projects with ease in future. Also a basic example of Model-View-Controller (MVC) design pattern will be implemented so that you can identify different components of a Struts Project going on forward.


Near the end we will have a taste of Struts Tags library to easily access variables defined within Action handler.


In case at any point during this tutorial you are confused about how things are working, you are highly recommended to read this Hello World! – Struts Framework Tutorial first, to develop an understanding of basic flow of Struts Application.



Tutorial’s Technology Stack:

Struts – 2.2.3
Eclipse – Helios



Download Starting Code:

Tutorial Starting Code: Download

How to Use: create a blank Dynamic Web Project using Eclipse naming “Tut-StrutsWithCustomAction”, and copy contents of this download to it. Refresh project in Eclipse and deploy on tomcat server to run this web application.



Step 1: Understanding Course of Action

The starting code for this tutorial has a simple navigation case implemented having two JSPs and two default Actions defined in strtus.xml against them.

We learned in Hello World tutorial that if ‘class’ attribute is not defined for Action tag in struts.xml, then by default com.opensymphony.xwork2.ActionSupport class is invoked in background which simply returns a success message. This success message is used by ‘result’ tag (default behavior again) to load page defined in it.

1
2
3
<action name="hello">
	<result>/jsp/hello.jsp</result>
</action>

What we will achieve in this tutorial is to override the default behavior of ‘action’ tag in order to use our Custom class. This way we can work with our Model objects, perform action, store information and return a custom View, thus practicing the complete MVC flow.



Step 2: Setting folder structure for Struts Project

We will organize our custom classes so that Struts Project’s folder structure remains maintainable as the project grows. Idea is to separate all Action controllers in action package, and model classes in model package. So let’s create Model and Action classes in next steps, their package names will setup the required folder structure.



Step 3: Creating Model Class

We will create a basic class to mimic a Model object, so that we can see how Model objects are going to be used in custom Action controllers of a Struts based web application.

Create a class (Right click on Project > New > Class) with following lines of code with package ‘sawan.hello.model’ and name ‘MessageStore’, leaving everything else as default. (The class implementation is borrowed from Apache Struts Tutorial written originally by Bruce Phillips).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package sawan.hello.model;
 
/**
 * Model class that stores a message.
 * @author Bruce Phillips
 *
 */
 
 public class MessageStore {
 
	private String message;
 
	public MessageStore() {
 
		setMessage("Hello Struts User");
	}
 
	public String getMessage() {
		return message;
	}
 
	public void setMessage(String message) {
		this.message = message;
	}
}



Step 4: Creating Class for custom Controller

Now will create a simple Java Class which in next step will be promoted to a Struts Action controller, so that we can understand how Struts framework is adding capabilities to plain old java objects (POJOs).

Create a class (Right click on Project > New > Class) with package ‘sawan.hello.action’ and name ‘HelloWorldAction’.

Following lines of code are generated automatically in the blank class by IDE.

1
2
3
4
5
package sawan.hello.action;
 
public class HelloWorldAction {
 
}

This class is going to use an object from our Model i.e. MessageStore class. So let’s create an instance variable within HelloWorldAction.

Add this line of code between curly brackets.

1
private MessageStore messagestore;

IDE will complain for ‘MessageStore’ cannot be resolved to a type, and it will highlight MessageStore type in our variable declaration.

Tip: In Eclipse, Simply click and hover over MessageStore class name and in proposed list of quick fixed select Import sawan.hello.model.MessageStore.

Hint: IDE was able to locate this class because we have Struts jar dependencies in WebContent/WEB-INF/lib folder.

Adding import statement before class definition will resolve this issue.

1
import sawan.hello.model.MessageStore;

Next we need to create getters and setters for this class variable.

Tip: In Eclipse, select Source > Generate Getters and Setters to auto generate them.

Following methods should be added under our variable declaration.

1
2
3
4
5
6
7
	public MessageStore getMessagestore() {
		return messagestore;
	}
 
	public void setMessagestore(MessageStore messagestore) {
		this.messagestore = messagestore;
	}

So far our HelloWorldAction class is a POJO having no Struts capabilities. We’ll add them next.



Step 5: Converting a POJO Class into a custom Struts Action Controller

This transformation needs two changes to our class and we’ll be all set.

Change 1: First of all, our class should inherit from ActionSupport class defined in Struts framework. Extending this class will not only force us to implement some predefined interfaces, but our class will also inherit some methods and properties from ActionSupport class and its parent classes. This is what inheritance does.

So let’s add ‘extends ActionSupport’ next to our class declaration, so it will look like:

1
public class HelloWorldAction extends ActionSupport

Tip: Once again, IDE will complain for unavailable ActionSupport class, so clicking and hovering will propose a quick fix to import import com.opensymphony.xwork2.

Adding this import statement will resolve this issue (if not automatically added for you):

1
import com.opensymphony.xwork2.ActionSupport;

Change 2: Second change to our HelloWorldAction is to provide an entry point for Struts front controller (defined in web.xml). Struts implements this interface by providing a class method named ‘execute’.

Also execute method must return a string.

So let’s add execute method.

1
2
3
4
public String execute()throws Exception
{	
    return SUCCESS;		
}

The variable SUCCESS is inherited from ActionSupport class, which inherited it from Action class, both being part of Struts Framework and are included in package com.opensymphony.xwork2.

Once our execute method is available, we need to initialize our ‘messagestore’ class variable so that it will be made available to resulting view.

Add this line of code within execute method to initialize class variable with our Model object.

1
messagestore = new MessageStore();

After both Step 4 and 5, our HelloWorldAction.java class should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package sawan.hello.action;
 
import com.opensymphony.xwork2.ActionSupport;
 
import sawan.hello.model.MessageStore;
 
public class HelloWorldAction extends ActionSupport {
 
	private MessageStore messagestore;
 
	public String execute()throws Exception
	{
		messagestore = new MessageStore();
		return SUCCESS;		
	}
 
	public MessageStore getMessagestore() {
		return messagestore;
	}
 
	public void setMessagestore(MessageStore messagestore) {
		this.messagestore = messagestore;
	}
}



Step 6: Adding custom Action configuration to struts.xml

Our custom Action class is ready to handle requests. But we have not told our web application, which requests should be forwarded to this Action controller.

Open src/struts.xml file. There are couple of actions already defined in downloaded source code. Let’s add our custom action after those.

Add following configuration block between ‘package’ opening and closing tags.

1
2
3
<action name="helloaction" class="sawan.hello.action.HelloWorldAction" method="execute">
	<result name="success">/jsp/helloaction.jsp</result>
</action>

What this Action configuration does is:

1. it defines a name for this action as ‘helloaction’, which will make it searchable by Struts front controller (one defined in web.xml).

2. class attribute sets the class which should be passed the execution.

3. method attribute defines the method name, which should be passed the execution in that class.

4. result tag, declares that when execution method finishes with a returned message, application should return /jsp/helloaction.jsp View.

5. name attribute within result tag, tells that redirect user to said page, only if message returned from execute method is success.

With this configuration we have set enough directions for our front controller defined in web.xml i.e. org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

However there is no ‘helloaction.jsp’ page defined yet, to which we are redirecting the user after successful exection, so we need to do that next.



Step 7: Adding result View for our custom Action

Create a new jsp page in ‘WebContent/jsp/’ folder named ‘helloaction.jsp’.

At this point since all required files and folders are created, so our project hierarchy should look like this when seen in Project Explorer.

Struts With Custom Action - folders and files in Project Explorer view

Folder structure when all required files are created

If we launch our application at this point, it will be launched fine, however there is no way to trigger a request to ‘helloaction’, which when intercepted by front filter, is redirected to our custom Action class.

Thus, we need to make changes to our index.jsp page, so that there is a link which we can hit to trigger all that. Change existing line of html code between body tags of index.jsp, to something like:

1
Index Page | <a href="hello">Struts</a> | <a href="helloaction">Custom Action</a>

Now if we launch our application index.jsp page will be displayed as default entry point.

Struts With Custom Action - default view for our application

Index page for our application

Clicking on ‘Custom Action’ link will generate this url request:

http://localhost:8080/Tut-StrutsWithCustomAction/helloaction

This request will be intercepted by our front filter, and it will look in struts.xml for a matching action name. Since it has truncated everything else, and only looking for ‘helloaction’, it will find it for sure, since we just added it during struts.xml configuration step above.

Front controller will pick the class name from ‘class’ attribute and pass the execution to ‘execute’ method of this class, just as defined in Action configuration. So execution will enter in execute method of our custom Action class’s execute method.

Once there, we have initialized the messagestore class variable with MessageStore, our model class, and simply retuned SUCCESS.

When execution comes back to front controller, it will use ‘result’ tag to determine which page to launch based on the value of returned string. Since we have returned SUCCESS and there is a result tag, with name success, front controller will redirect browser to helloaction.jsp

Hint: It is a common and recommended approach to define class variables within Action class with required values returned by Model. So that resulting view will only have access to values which it needs to display.



Step 8: Using Struts Tag Library to access variables within Action controller

At this point our basic flow is working fine and we have utilized a custom Action controller for processing our page requests.

However the redirected helloaction.jsp page is blank. In real world applications, we will be doing some processing within execute method, and displaying the results on redirected page (helloaction.jsp in our case).

Struts facilities this functionality very elegantly by providing Struts Tag Library. Using struts tags, we can very easily access properties we have set within Action controller for each request.

For making our helloaction.jsp capable of accessing property defined within HelloWorldAction class, we need to make two changes in helloaction.jsp

Change 1: First of all we need to add Tag Library Directive, so that web server knows how to render Struts 2 Tags when generating a response.

Add this line of code on top of helloaction.jsp page right under page directive.

1
<%@ taglib prefix="s" uri="/struts-tags" %>

Change 2: Secondly we need to use one of Struts 2 Tag to access the property within response, which is available to us within our page scope.

Add this line of code between body tag of helloaction.jsp:

1
<h2><s:property value="messagestore.message" /></h2>

After these changes, our helloaction.jsp should look something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello Struts Tag Library</title>
</head>
<body>
<h2><s:property value="messagestore.message" /></h2>
</body>
</html>

Let’s run our web application once again, this time when helloaction.jsp page is rendered, we will see same message defined in our Model object i.e. MessageStore.java.

Using Struts Tag Library to display property defined in our custom Action

Using Struts Tag Library to display property defined in our custom Action



Download Tutorial Code:

Tutorial Working Code: Download



Exercise:

  • Add another custom Action handler along with its configuration in struts.xml file.

  • Use any other message besides “Success” returned from execute method. Use messages defined in Action interface within Struts 2 API.


    Hint: You will also have to make changes in struts.xml so that result will respond to that returned message.

  • Can we use different method name besides execute in struts.xml ? will that method act as our default entry point if we satisfy the requirement of returning a string from that method?


Hello World! – Struts Framework Tutorial

**adsense_4x1Block**
Introduction:


In this tutorial we will develop our Hello World java Web Application using Struts technology. The Apache Struts web framework is a free open-source solution for creating Java web applications using Model View Controller (MVC) design pattern.

Let’s get started with a very basic tutorial that will expose limited capabilities of Struts framework, but it will serve as a good starting point to explore Struts further by understanding the initial configurations required.

Tutorial’s Technology Stack:

Struts 2.2.3
Eclipse Helios (But you can do same steps with NetBeans as well)



Step 1: Creating Java Web Project in Eclipse IDE

This tutorial assumes you already know how to create new Java based Dynamic Web Project in Eclipse. If not, then you must first acquire some understanding using this basic JSP Tutorial

To continue we need a new Web Project, named ‘Tut-StrutsHelloWorld’ with index.jsp page added.



Step 2: Customizing JSP Page and Adding Navigation

Before diving into Struts let’s create a simple case of navigation to verify Struts working. Besides an index.jsp page in WebContent folder, add another jsp and name it ‘hello.jsp’

Refer this page from index.jsp, by pasting this line of code between body tags.

1
Index Page | <a href="hello">Struts</a>

Let’s add some custom text in ‘hello.jsp’ as well so that page is not rendered blank. Add following line of code in ‘hello.jsp’ between body tags:

1
<b>Hello World! Struts Application</b>

With this we are all set as far as our basic navigation is concerned.



Step 3: Adding Struts Capability to our project

Struts capability can be added in a project by simply adding its distributed jar files. Download latest Struts distribution from Apache Struts project site. This tutorial was written using Struts 2.2.3, so same or later can be downloaded.

Extract files from this distribution; some contained folders are described below:

apps: contain sample applications against tutorials on struts project website
docs: this folder contains, documentation for struts plugins, test pages, and whole Apache Struts project website, including tutorials, so that you can work on them offline as well.
lib: this folder contains struts jar files (containing struts implementation) and many other related jars, that you might need to use based on your project’s future needs. e.g. in case you plan to integrate it with Spring, then you’ll need related jar files.
src: since struts itself is an open source project maintained by Apache, that’s why its source code is included in the distribution itself.

Let’s now shop for our desired jar files from lib folder. Copy following jars from distribution lib folder, and paste them in:

Tut-StrutsHelloWorld\WebContent\WEB-INF\lib

  • struts2-core-2.2.3.jar
  • xwork-core-2.2.3.jar
  • commons-fileupload-1.2.2.jar
  • commons-io-2.0.1.jar
  • commons-lang-2.5.jar
  • freemarker-2.3.16.jar
  • javassist-3.11.0.GA.jar
  • ognl-3.0.1.jar

These are the minimal jars that you’ll need for Struts 2.2.3. Of course the version number may vary based on which distribution you have downloaded.

Are you wondering, there are so many jars in lib folder within Struts distribution, how on earth would I know which jars to pick up and which to leave? What I did was, at first added struts2-core-2.2.3.jar only, and Ran the application within Eclipse. There was an exception stating ‘class not found’ giving package name in which it looked for the class.

That package name helped me identify the jars required from lib folder, so I picked it and copied that jar to my project’s lib folder (Tut-StrutsHelloWorld/WebContent/WEB-INF/lib). I repeated this step unless there was no exception in Console. So it is up to you now, if you want you can go through this exploration step or you can simply pick the ones I have already listed.



Step 4: Telling Server we are using Struts

At this point if you will run your project on Server, nothing will happen. Since we just added some jars and they are sitting there doing nothing, unless we use some object from Struts implementation in these jars.

For enabling Struts 2 framework to work with our web application, we need to add a special Servlet, implemented by Struts called ‘StrutsPrepareAndExecuteFilter’, which is responsible for initializing Struts 2 for our project.

Since it is a Servlet, and from Hello World – Servlets Tutorial, we know that Servlets need to be loaded by Web Server (e.g. Tomcat) when application is deployed. And Web Server reads this information from entry point of our web project i.e. web.xml, the web application descriptor file.

So Add this code in web.xml between web-app tag.

1
2
3
4
5
6
7
8
9
<filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
 
<filter-mapping>
  <filter-name>struts2</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

The Servlet that initializes Struts 2 is a special Servlet with filtering capabilities thus called Filter. A Filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both. Filters are actually an interface based on Servlets, thus they are basically Servlets.

Thus we added two nodes ‘filter’ and ‘filter-mapping’, rather than usual ‘servlet’ and ‘servlet-mapping’, since filter is a Servlet in effect, but just a little special.

Also note that, url-pattern node value is /* meaning the Struts 2 filter will be applied to all URLs for this web application. Thus it acts as a front filter and controls what should be done with each request to our web project’s internal resources. Hence acting as a Controller, making C part of MVC.



Step 5: Configuring our Struts 2 Implementation

The Filter Servlet we created above, needs a configuration file to know, what it should filter and how to behave with incoming requests (i.e. when new page is requested by the user). This configuration is actually what customizes Struts 2 for our web application.

So create a new file named ‘struts.xml’ , and place it in Tut-StrutsHelloWorld/src folder (struts.xml must be on the web application’s root class path)

Add these lines of code in src\struts.xml file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
 
<struts>
      <!— Makes struts to output more error information in console in devMode  -->
	<constant name="struts.devMode" value="true" />
 
	<!— has nothing to do with java packages, simply used to group actions (below).
    	    name attribute can have any value. Extend it from struts-default -->
	<package name="hello" extends="struts-default">
 
		<!—  action for index.jsp page -->
		<action name="index">
			<result>/index.jsp</result>
		</action>
 
		<!-- action for hello.jsp -->
		<action name="hello">
			<result>/hello.jsp</result>
		</action>		
	</package>
</struts>

Note: Struts 2 can use either an XML configuration file or annotations (or both) to specify the relationship between a URL, a Java class, and a view page (such as index.jsp). For our basic Struts 2 application, we’ll use a minimal xml configuration.



Step 6: Understanding Basic Flow of Struts Application

Very important to understand what these lines of configurations will tell our StrutsPrepareAndExecuteFilter and what is happening in the background.

Within the Package named “hello” we have grouped two Actions. Actions are Fundamental component of Struts framework. From Apache’s website:

“An Action is an adapter between the contents of an incoming HTTP request and the corresponding business logic that should be executed to process this request”

meaning, when our application launches, web server reads the web.xml. it finds welcome-file-list tag, and in that it tries all welcome-files including index.jsp, to launch default request to our application’s index page.

Remember? the Servlet filter we have configured in web.xml has a filter-mapping defined so that it will listen to every request (/* )coming to our application. So it will kick in, as soon as web server launches a request to find our index page. Now what Struts filter will do is, first of all it will remove all the unnecessary strings from the Request URL. e.g. in case of this URL:

http://localhost:8080/Tut-StrutsHelloWorld/index.jsp

Filter will remove the host and project name, and also the .jsp extension. Taking only ‘index’. That’s how Struts is implemented.

Now it will take that request (whatever is left of it) and scan through struts.xml, in top down sequence, and try to find an Action that has exact same name as this sub-string.

Yes it will find it since we have defined an Action with name attribute set as ‘index’. So now what.

Once matching Action configuration is found by the Filter, it will call the java Class associated with that Action. What? Which class, there is no class association in configuration. Yes, for hello world struts tutorial, I have kept it simply, and to the defaults. So when the class attribute in an action mapping is not defined, the com.opensymphony.xwork2.ActionSupport class is used as a default.

Had there been a class defined, filter would pass the execution to ‘execute’ method defined by our custom class. By default since ActionSupport class is used, so it’s execute method returns a string “success” by default.

what will we do with this string “success”? actually < result > tag within Action will do. By default result tag listens and responds to “success” message. So when it received the success message from ActionSupport by default, it redirected our browser to page named /index.jsp.

Now when index.jsp page is rendered, it has a link to “hello”. Clicking on will generate a request to webserver, which it will redirect to filter listening to all requests within our application. Filter will go through the above process once again, this time matching the Action named “hello” instead and showing the result “hello.jsp” page this time.



Step 7: Running our first Struts based Web Application

So now with this understanding, we are good to build and deploy our first Struts based web application on web server. Provided web server is configured with Eclipse IDE, right click on project name and select Run As > Run on Server. Built in browser will be launched with first showing the index.jsp page, and clicking on Struts link will navigate to “hello.jsp” after going through the background Struts Actions mapping mechanism.



Hello World Struts - rendered index page

Hello World Struts - rendered index page



Clicking on Struts link will navigate to hello.jsp.



Hello World Struts - rendered hello strutspage

Hello World Struts - rendered hello strutspage



Exercise

  • Rename the Action’s name attribute for hello, to something else. Where else do you need to change the action name?

    Hint: compare the code snippets above and see where that name matches.

  • Add a link on index page for a third page and call it mystruts.jsp. Add required configurations in struts.xml to make this new navigation work. (Hint: you need to add an Action)
  • Go through the Configuration Elements Documentation and read about different elements.