Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access the Struts value stack from the HttpServletRequest object?

Tags:

java

struts2

I have come across some code that is accessing a value that is stored in the struts value stack by simply calling getAttribute() on the HttpServletRequest object. I didnt think this was possible and where is it documented?

Code from the action class (it does not add it to class only to the value stack):

private PaginatedChunk searchResults;   


public PaginatedChunk getSearchResults() {
    return searchResults;
}

public void setSearchResults(PaginatedChunk searchResults) {
    this.searchResults = searchResults;
}

This is the code in a custom tag that pulls the value from the request (and it works!?):

HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
PaginatedChunk searchResults = (PaginatedChunk)  request.getAttribute("searchResults");

Can someone explain to me how this works? I thought the value Stack wasn't directly accessible through the request.

We are running struts2 v2.1.8.1

like image 361
Java Dev Avatar asked Aug 04 '11 17:08

Java Dev


1 Answers

At first glance I would definitely agree. What you show does not look intuitive. But what is really happening is gaining access to the request object from the value stack, not really vice versa. You start with pageContext in the value stack, and you are still working with something at the end which still has access to the value stack (it also has access to the request too). Here is how it happens:

Looking here ( http://www.docjar.com/html/api/org/apache/struts2/ServletActionContext.java.html ) we see where "pageContext" comes from:

   93       public static PageContext getPageContext() {
   94           return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT);
   95       }

getContext().get() returns an Object, which we know is a kind of PageContext. But what is the implementing class?

Creating a simple action:

package com.quaternion.action.test;

import com.opensymphony.xwork2.ActionSupport;

public class RequestAccessTest extends ActionSupport{
    public String getGreeting(){
        return "Hello from Request AccessTest";
    }
}

Then in the JSP:

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <body>
        <h1>Request Access Test</h1>
        <%
            HttpServletRequest r = (HttpServletRequest) pageContext.getRequest();
            String aGreeting = (String) r.getAttribute("greeting");
            System.out.println(aGreeting);
            System.out.println("R's class is:" + r.getClass().getCanonicalName());
        %>
    </body>
</html>

On my console I see printed:

INFO: Hello from Request AccessTest
INFO: R's class is:org.apache.struts2.dispatcher.StrutsRequestWrapper

So we are really dealing with a StrutsRequestWrapper (Now that we know what we're actually dealing with it's easy)...

http://massapi.com/source/struts-2.2.1/src/core/src/main/java/org/apache/struts2/dispatcher/StrutsRequestWrapper.java.html

Looking at the above link We see that getAttribute is indeed overridden.

Starting at line 65, we see it tried to get the value out of the request, and then if that fails it goes on to get it out of the value stack.

Where is this documented? I guess it's documented here, as of now ;)

like image 134
Quaternion Avatar answered Sep 19 '22 15:09

Quaternion