Struts2 in Nutshell

Tuesday, February 24, 2009

Struts2 in Nutshell

Struts2

The Struts2 framework comes with tons of new powerful features. The struts core functionality goes hand to hand with Spring 2 framework. Let us see the core features of the Struts2 framework.

  1. Multithread support

The Action class can be a simple POJO with mutator methods and simple execute method. The framework creates separate instance for each user request and destroys it upon completing the request. It provides the thread safe flexibility.

  1. Interceptors

The framework allows the user request to be intercepted and processed by using the interceptors.

  1. Dependency Injection

The Action class does not need to inherit the Action or ActionSupport interface. So how does the Action class get the handle of http objects such as Http request, response and etc? The spring dependency injection sets the object instance at run time.

  1. Validation

The validation can be done at Action class by just implementing the validate method or validation xml would do.

Setting up

Required Jars

Place the following struts jar files in the class path in order to run the simple hello world example. You can copy the files from /lib folder.

1. common-fileupload-1.2.1.jar

2. commons-lang-2.3.jar

3. commons-logging-1.0.4.jar

4. freemarker-1.3.13.jar

5. ojnl-2.6.11.jar

6. struts2-core-2.1.6.jar

7. xwork-2.1.2.jar

FilterDispatcher

The first step is configuring the FilterDispatcher in the web.xml. The FiteteDispatcher takes the action package names as a parameter in the web.xml. The Dispatcher receives the user request and delegates it to the interceptor and/or action classes.

xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

<display-name>Struts2Tutorialdisplay-name>

<filter>

<filter-name>struts2filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcherfilter-class>

<init-param>

<param-name>actionPackagesparam-name>

<param-value>com.struts2tutorial.actionparam-value>

init-param>

filter>

<filter-mapping>

<filter-name>struts2filter-name>

<url-pattern>/*url-pattern>

filter-mapping>

web-app>

Action Class

The Action can be a simple POJO with a execute method returning a string or extend the ActionSupport. It is a thread safe and supports the multithreading. As explained earlier the struts runtime creates the separate instance for each request. The action has mutator methods for the variable message. It sets the welcome message in execute method.

/**

*

*/

package com.struts2tutorial.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

/**

* @author Elangovan Mohan

*

*/

public class HelloWorldAction extends ActionSupport {

private String message;

@SuppressWarnings("unused")

private HttpServletRequest request;

/* (non-Javadoc)

* @see com.opensymphony.xwork2.ActionSupport#execute()

*/

@Override

public String execute() throws Exception {

setMessage("Struts 2 is up and running");

return SUCCESS;

}

/**

* @return the message

*/

public String getMessage() {

return message;

}

/**

* @param message the message to set

*/

public void setMessage(String message) {

this.message = message;

}

}

Struts.xml

The Struts xml acts as a registry for the runtime. The action class is configured with result page. The action redirects or forwards the request to the destination based on the result. The result can be Success, Error, Input, Login and None. The Success will be used as default if the result is not explicitly set. The Struts.xml resides under your src folder.

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>

<package name="Struts2Tutorial" extends="struts-default">

<action name="HelloWorld" class="com.struts2tutorial.action.HelloWorldAction">

<result>/HelloWorld.jspresult>

action>

struts>

HelloWorld.jsp

Let us create the first HelloWorld.jsp.

<%@ 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>Insert title heretitle>

head>

<body>

<s:label key="label.message">s:label><s:property value="message"/>

body>

html>

Localization

The property files are broken into multiple files. The default property file is a package.properties. The file resides under the src folder.

label.message=Welcome Message

Ready to Test

The url http://localhost:8080/Struts2Tutorial/HelloWorld.action brings the HelloWorld jsp



Validation

The Struts framework provides the comprehensive validation. The validation can be done programmatically or can be defined in the validation xml.

Modify HelloWorld.jsp

The Html URL link to the logon page is included in the HelloWorld.jsp page. The HelloWorldAction receives the request and forwards to the LogOn page.

<%@ 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>Insert title heretitle>

head>

<body>

<s:label key="label.message">s:label><s:property value="message"/>

<a href="<s:url action="HelloWorld?logOn=true"/>">LogOna>

body>

html>

Modify HelloWorldAction

Here we have added mutator method for the logOn variable. The action forwards the request to the LogOn page if the logOn value is set to true. The condition is added in the execute method.

/**

*

*/

package com.struts2tutorial.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

/**

* @author Elangovan Mohan

*

*/

public class HelloWorldAction extends ActionSupport implements ServletRequestAware {

private String message;

private String logOn;

@SuppressWarnings("unused")

private HttpServletRequest request;

/* (non-Javadoc)

* @see com.opensymphony.xwork2.ActionSupport#execute()

*/

@Override

public String execute() throws Exception {

if(!StringUtils.isEmpty(getLogOn()) && StringUtils.equalsIgnoreCase("true", getLogOn())) {

return "logOn";

}

setMessage("Struts 2 is up and running");

return SUCCESS;

}

/**

* @return the message

*/

public String getMessage() {

return message;

}

/**

* @param message the message to set

*/

public void setMessage(String message) {

this.message = message;

}

/**

* @return the logOn

*/

public String getLogOn() {

return logOn;

}

/**

* @param logOn the logOn to set

*/

public void setLogOn(String logOn) {

this.logOn = logOn;

}

/**

*

*/

private static final long serialVersionUID = 5077311997220977732L;

public void setServletRequest(HttpServletRequest arg0) {

this.request=arg0;

}

}

LogOn.jsp

Let us create a simple LogOn.jsp. It takes two html parameters such as username and password.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>

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

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>Insert title heretitle>

head>

<body>

<s:form action="LogOn">

<s:textfield key="label.userName" name="username">s:textfield>

<s:password key="label.password" name="password">s:password>

<s:submit name="submit">s:submit>

s:form>

body>

html>

LogOnAction

The setter and getter methods for the username and password are defined in the LogOnAction class. The class attributes can be defined in a separate model also. The ModelDriven interface supports it. The action class can access the Http request by implementing the ServletRequestAware interface. The interceptor injects the instance at the run time. The interceptor for modeldriven and request aware should be configured for the action class at struts.xml.

/**

*

*/

package com.struts2tutorial.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

/**

* @author Elangovan Mohan

*ModelDriven,

*/

public class LogOnAction extends ActionSupport implements ServletRequestAware{

private String username;

private String password;

@SuppressWarnings("unused")

private HttpServletRequest request;

/**

* @return the username

*/

public String getUsername() {

return username;

}

/**

* @param username the username to set

*/

public void setUsername(String username) {

this.username = username;

}

/**

* @return the password

*/

public String getPassword() {

return password;

}

/**

* @param password the password to set

*/

public void setPassword(String password) {

this.password = password;

}

/**

*

*/

private static final long serialVersionUID = -5994107269216529622L;

/* (non-Javadoc)

* @see com.opensymphony.xwork2.ActionSupport#execute()

*/

@Override

public String execute() throws Exception {

return SUCCESS;

}

public void setServletRequest(HttpServletRequest arg0) {

this.request=arg0;

}

}

Validation

A validation xml starting the action class should be created and reside along with the action class. In our case, the log on validation file name will be LogOnAction-validation.xml.

DOCTYPE validators PUBLIC

"-//OpenSymphony Group//XWork Validator 1.0.2//EN"

"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

<validators>

<field name="username">

<field-validator type="requiredstring">

<message>User Name is requiredmessage>

field-validator>

field>

<field name="password">

<field-validator type="requiredstring">

<message>Password is requiredmessage>

field-validator>

field>

validators>

Package.proerties

Update the package.properties with the following.

label.userName=Username

label.password=Password

Struts.xml

You can define the action mapping for the LogOnAction.

<action name="LogOn" class="com.struts2tutorial.action.LogOnAction">

<result>/LogOn.jspresult>

<result name="input">/LogOn.jspresult>

action>

Ready to Test

You can test this validation by invoking this url http://localhost:8080/Struts2Tutorial/HelloWorld.action?logOn=true. It will display the following page.



The page comes with the error message upon clicking the submit button.


References

http://www.struts2.org/category/struts2-validation/

http://www.struts2.org/category/struts2-validation/

http://www.infoq.com/articles/converting-struts-2-part1

http://struts.apache.org/2.x/docs/comparing-struts-1-and-2.html

http://struts.apache.org/2.1.6/docs/tutorials.html

Downloads

http://struts.apache.org/download.cgi#struts216

Troubleshooting

You need to make sure the following before you start running your app. This will solve the action class not found errors.

  • The FilterDispatcher is configured in the web.xml.
  • Struts.xml is defined with action mapping and kept under src folder.
Package.properties with the labels.

Followers