How to get Servlet Session, Request, Response, Context Attributes in Struts 2 Action

Struts 2 Action classes doesn’t provide any methods to get Servlet API Request, Response, Session and attributes. But sometimes we need to access these in action classes, for example checking HTTP method or to work with session attributes or to set cookies or headers in response.

That’s why Struts 2 API provides a bunch of interfaces that we can implement in action classes to inject these objects in Action classes. All of these interfaces end with “Aware” and defined in org.apache.struts2.interceptor package.

All of these interfaces declares setter methods through which Struts 2 API injects Servlet API components in action classes. It’s a great example of Dependency Injection in Java EE frameworks.

These *Aware interfaces are:

  1. SessionAware: This interface provides access to session attributes in action classes and declare a single method setSession(Map sessionAttributes). Note that we can’t get HttpSession by implementing this interface, this is just to get access to the session attributes.
  2. ApplicationAware: This interface provides access to context attributes in action classes as Map. We can add attributes to application context by putting values in the context map. This interface declares single method setApplication(Map applicationAttributes).
  3. RequestAware: This interface provides access to request attributes in action classes, it contains single method setRequest(Map requestAttr). This interface is only applicable if Action classes are used in Servlet environment. Since this interface makes the Action tied to a servlet environment, so it should be avoided if possible since things like unit testing will become more difficult.
  4. ServletRequestAware: We can implement this interface in action classes to get access to HttpServletRequest object. This interface is only relevant if the Action is used in a servlet environment. It defines a single method as setServletRequest(HttpServletRequest request).
  5. ServletResponseAware: Struts 2 action classes can implement this interface to get access to the HttpServletResponse object. We can then use response object to add headers or cookies. It defines a single method as setServletResponse(HttpServletResponse response).
  6. CookiesAware: This interface is intended to provide access to cookies in request in the form of Map. It contains single method setCookiesMap(Map cookies). To work with this interface, there are two interceptors defined in struts-default package as:
                <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
                <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
    

    But they are not part of defaultStack interceptors stack, so we need to include them for action class like below.

    		<action name="home" class="com.journaldev.struts2.actions.HomeAction">
    			<interceptor-ref name="cookie"></interceptor-ref>
    			<interceptor-ref name="cookieProvider"></interceptor-ref>
    			<interceptor-ref name="defaultStack"></interceptor-ref>
    			<result name="success">/home.jsp</result>
    		</action>
    

    However these interceptors are very new and in my testing with Struts 2 version 2.3.15.1, I didn’t find it to be working. I looked into Struts 2 API docs but didn’t find any help on this. I will update the post if I find anything or if you know what is missing, please let us know through comments. The workaround is to use ServletRequestAware and ServletResponseAware interface to get the request cookies or to set cookies in response.

  7. PrincipalAware: We can implement this interface in action class to get Principal information from HttpServletRequest object. This interface works with PrincipalProxy to provide user id, principal details.

Let’s see all these interfaces in action with a simple Struts 2 project. Our final project structure looks like below image.

Struts-2-Example-Project

Configuration Files

<?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"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<display-name>Struts2Example</display-name>

	<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>
</web-app>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>Struts2Example</groupId>
	<artifactId>Struts2Example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	
	<dependencies>
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-core</artifactId>
			<version>2.3.15.1</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
		</plugins>
		<finalName>${project.artifactId}</finalName>
	</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
	<constant name="struts.convention.result.path" value="/"></constant>
	<package name="user" namespace="/" extends="struts-default">
		<action name="login">
			<result>/login.jsp</result>
		</action>
		<action name="home" class="com.journaldev.struts2.actions.HomeAction">
			<interceptor-ref name="cookie"></interceptor-ref>
			<interceptor-ref name="cookieProvider"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result name="success">/home.jsp</result>
		</action>

	</package>

</struts>

The configuration files are self explanatory and easy to understand.

JSP Pages

<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<%@ 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=US-ASCII">
<title>Login Page</title>
</head>
<body>
<s:form action="home" method="post">
<s:textfield label="User Name" name="user"></s:textfield>
<s:textfield label="Password" name="password"></s:textfield>
<s:submit label="Login"></s:submit>
</s:form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<%@ 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=US-ASCII">
<title>Home Page</title>
</head>
<body>
<h3>Welcome <s:property value="user"/></h3>
</body>
</html>

JSP pages are also very simple and just used to send some data in request and then use them in result page.

Action Class

package com.journaldev.struts2.actions;

import java.util.HashMap;
import java.util.Map;

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

import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.CookiesAware;
import org.apache.struts2.interceptor.PrincipalAware;
import org.apache.struts2.interceptor.PrincipalProxy;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class HomeAction extends ActionSupport implements SessionAware,
		ApplicationAware, CookiesAware, RequestAware, ServletRequestAware,
		ServletResponseAware, PrincipalAware {

	private static final long serialVersionUID = 1L;

	@Override
	public String execute() {
		System.out.println("Request Method: " + request.getMethod());
		System.out.println("Using HTTPS?: " + principalProxy.isRequestSecure());
		System.out.println("Request Cookies:" + requestCookies);
		// add a cookie to response
		response.addCookie(new Cookie("user", "Pankaj"));
		if (requestCookies == null)
			requestCookies = new HashMap<String, String>();
		requestCookies.put("test", "test");

		System.out.println("Session Attributes: " + sessionAttributes);
		// add session attribute
		HttpSession mySession = request.getSession();
		mySession.setAttribute("user", "Pankaj");
		//OR
		sessionAttributes.put("test", "Test");

		System.out.println("Context Attributes: "
				+ contextAttributes.get("user"));
		// add context attribute
		contextAttributes.put("user", "Pankaj");

		System.out.println("Request Attributes: " + requestAttributes);
		return SUCCESS;
	}

	// variables for *Aware interfaces
	private PrincipalProxy principalProxy = null;
	private HttpServletRequest request = null;
	private HttpServletResponse response = null;
	private Map<String, Object> requestAttributes = null;
	private Map<String, Object> sessionAttributes = null;
	private Map<String, Object> contextAttributes = null;
	private Map<String, String> requestCookies = null;

	@Override
	public void setPrincipalProxy(PrincipalProxy principalProxy) {
		this.principalProxy = principalProxy;
	}

	@Override
	public void setServletResponse(HttpServletResponse httpServletResponse) {
		this.response = httpServletResponse;
	}

	@Override
	public void setServletRequest(HttpServletRequest httpServletRequest) {
		this.request = httpServletRequest;
	}

	@Override
	public void setRequest(Map<String, Object> requestAttr) {
		this.requestAttributes = requestAttr;
	}

	@Override
	public void setCookiesMap(Map<String, String> cookies) {
		this.requestCookies = cookies;
	}

	@Override
	public void setApplication(Map<String, Object> applicationAttributes) {
		this.contextAttributes = applicationAttributes;
	}

	@Override
	public void setSession(Map<String, Object> sessionAttr) {
		this.sessionAttributes = sessionAttr;
	}

	// java bean properties to hold request attributes
	private String user;
	private String password;

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

A single action class implementing all the *Aware interfaces and using them to log some data in server log files.

Once we execute the login action and then hit home action multiple times, we get following logs.

Request Method: POST
Using HTTPS?: false
Request Cookies:{}
Session Attributes: {}
Context Attributes: null
Request Attributes: {struts.valueStack=com.opensymphony.xwork2.ognl.OgnlValueStack@662fe032, __cleanup_recursion_counter=1, struts.actionMapping=ActionMapping{name='home', namespace='/', method='null', extension='action', params=null, result=null}}
Request Method: POST
Using HTTPS?: false
Request Cookies:{}
Session Attributes: {test=Test, user=Pankaj}
Context Attributes: Pankaj
Request Attributes: {__cleanup_recursion_counter=1, struts.valueStack=com.opensymphony.xwork2.ognl.OgnlValueStack@749cd006, struts.actionMapping=ActionMapping{name='home', namespace='/', method='null', extension='action', params=null, result=null}}

Notice that request cookies are NULL, however I checked request and response in browser and it’s sending cookies in request.

That’s all for accessing Servlet API core components in Struts 2 Action classes. It’s simple and elegant to use.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe to JournalDev Newsletter
Get the FREE access to Monthly Newsletter and Free PDF eBooks
*No Spam Guaranteed. By entering your email address, you agree also subscribing to our newsletter.
Oops! - Something went wrong.
Close
Limited Offer: Java 8 Lambda Expressions PDF eBook Free Download Now
Exclusive Offer: Citrix™ Whitepaper on Denial of Service Attack Download Now