Webwork works with a Value Stack concept. Every object you need to access from WebWork, wether from the Action itself or from a JSP page, using the supplied taglibs, comes from the Value Stack.JSTL, on the other hand, works with request attributes. Usually, it would be very cumbersome to access the WebWork Value Stack from JSTL tags. The follwing is a one way to make JSTL work seamlessly with the WebWork Value Stack.The following filter wraps every HttpServletRequest on a custom class, overriding the getAttribute method. The overriden method will look in the Value Stack if a corresponding request attribute isn't found. This way, you can use JSTL to access the WebWork value stack without any further exercising.
JSTLFilter.java
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class JSTLFilter implements javax.servlet.Filter { FilterConfig _filterConfig; public FilterConfig getFilterConfig() {
return _filterConfig;
} public void setFilterConfig(FilterConfig filterConfig) {
_filterConfig = filterConfig;
} public void init(FilterConfig filterConfig) throws ServletException {
} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Make sure it is an HttpServletRequest, if so, create the wrapper and pass it on
if (request instanceof HttpServletRequest) {
ServletRequest wrappedRequest = new JSTLRequestWrapper((HttpServletRequest)request);
chain.doFilter(wrappedRequest, response);
} else {
// Otherwise, just pass the request on down the chain
chain.doFilter(request, response);
}
} public void destroy() { }
}
This is the filter that will wrap every request on the custom wrapper, detailed below. If you're using a servlet 2.3 container the filter may be run every time there is a forward / include. Try the following code to only run the filter once per request:public class JSTLFilter implements javax.servlet.Filter {
private static final String RUNONCE_REQUEST_ATTRIBUTE = "__run_once_" + JSTLFilter.class.getName();
private static final Object RUNONCE_REQUEST_VALUE = new Object();
FilterConfig _filterConfig;
public FilterConfig getFilterConfig() {
return _filterConfig;
}
public void setFilterConfig(FilterConfig filterConfig) { _filterConfig = filterConfig;
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Object attribute = request.getAttribute(RUNONCE_REQUEST_ATTRIBUTE);
// Make sure it is an HttpServletRequest, if so, create the wrapper and pass it on
if (attribute == null && request instanceof HttpServletRequest) {
ServletRequest wrappedRequest = new JSTLRequestWrapper((HttpServletRequest) request);
chain.doFilter(wrappedRequest, response);
request.setAttribute(RUNONCE_REQUEST_ATTRIBUTE, RUNONCE_REQUEST_VALUE);
} else {
// Otherwise, just pass the request on down the chain
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
JSTLRequestWrapper.java
import webwork.util.ValueStack;import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;public class JSTLRequestWrapper extends HttpServletRequestWrapper{
private ServletRequest wrappedRequest; public JSTLRequestWrapper(HttpServletRequest request) {
super(request);
wrappedRequest = request;
} public Object getAttribute(String s) {
Object attr = super.getAttribute(s);
if (null != attr) {
return attr;
} else {
// If not found, then try the ValueStack
ValueStack stack = ValueStack.getStack(wrappedRequest);
if (null == stack) return null;
else return stack.findValue(s);
}
}
}
This is the custom request wrapper that overrides the getAttribute method to also look in the Value Stack when a request attribute isn't found. Please note that the above code works only with WebWork 1.x, not with WebWork2. If you're using WebWork2, modify the getAttribute method:public Object getAttribute(String s) {
Object attribute = super.getAttribute(s);
if (attribute == null) {
// If not found, then try the ValueStack
OgnlValueStack stack = ActionContext.getContext().getValueStack();
if (stack != null) {
attribute = stack.findValue(s);
}
}
return attribute;
}
The filter mapping should look something like this (you'll probably want the filter to be in a more sensible package):<filter>
<filter-name>jstlfilter</filter-name>
<filter-class>JSTLFilter</filter-class>
</filter><filter-mapping>
<filter-name>jstlfilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping><filter-mapping>
<filter-name>jstlfilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>