Reputation: 593
I was wondering if I can capture the result of an action after the result returns and the JSP is rendered. I want to be able to take the entire result (generated HTML) and push it into memcached so I can bring it via Nginx with-out hitting the application server. Any ideas?
PS: I know I can run the interceptor after the action executes but before the result returns and the JSP is rendered, but not after the JSP is rendered.
Upvotes: 3
Views: 4366
Reputation: 1315
Hey I know its quite late now to answer you might have already found out the answer, however for others to benefit I am posting the answer.
One thing that is very similar to what you are doing is done by sitemesh filter.
Yes, filter comes before and after the Struts2 filter itself, so you can mess with the inputs and outputs easily.
But struts does evaluate JSP/freemarker/velocity and generate the final html which is passed to the user. JSP is a bit trickey because internally a servlet is called but check out org.apache.struts2.views.freemarker.FreemarkerResult class
, you can see the actual html getting generated in template.process(model, writer);
. This writer is actually ServletActionContext.getResponse().getWriter()
;
Now to get the html all you need to do is
ServletActionContext.getResponse().getWriter().toString() //This does not work out of box
. To get the toString() to work you need to use a ResponseWrapper - which is the same method to get result html in Filters. See- Programming Customized Requests and Responses.
Listing to modify resulting html in struts 2. This is not tested, but it is extracted from my code I have written earlier for custom template engine. I will probably post full description in Custom template engine for struts2
public class DecoratorInterceptor implements Interceptor {
public String intercept(ActionInvocation invocation) throws Exception {
final ActionContext context = invocation.getInvocationContext ();
HttpServletResponse responseParent = (HttpServletResponse)
context.get(ServletActionContext.HTTP_RESPONSE);
CharResponseWrapper wrapper = new CharResponseWrapper(responseParent);
ServletActionContext.setResponse(wrapper);
//Actual Action called
String result = invocation.invoke();
String htmlReturned = wrapper.toString();
//play with htmlReturned ...
String modifiedhtml = pushintoMemCache(htmlReturned );
CharArrayWriter car = new CharArrayWriter();
car.write(modifiedhtml );
PrintWriter out = responseParent.getWriter();
out.write(car.toString());
out.flush();
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
}
Upvotes: 1
Reputation: 31360
Within your interceptor's intercept()
method, the ActionInvocation
parameter has a getResult()
method which returns null
before Action execution (i. e. before you call invocation.invoke()
in your intercept()
method) and contains an implementation of Result
afterwards. That object should give you some way to access the data you need, but how this is done probably depends on the class that is actually used.
See also my somewhat related question and the answer I posted after figuring it out.
Upvotes: 0
Reputation: 2609
Question: How do you determine if the view has been generated? Do you set a request header or an some sort of a flag to determine if the view has been generated?
You could try throwing a MemCachedException to indicate that it is time to load into a mem cache. Your interceptor code could read
try {
return invocation.invoke();
} catch (MemCachedException mce) {
// Your code to upload to MemCache.
} finally {
// blah blah clean up.
}
Upvotes: 0
Reputation:
I haven't found a way to do this inside of struts2, your best bet it to create a servlet Filter and have it modify the OutputStream.
http://onjava.com/pub/a/onjava/2003/11/19/filters.html
Upvotes: 1
Reputation: 94645
Read this article - http://struts.apache.org/2.0.6/docs/interceptors.html
SUMMARY:When you request a resource that maps to an "action", the framework invokes the Action object. But, before the Action is executed, the invocation can be intercepted by another object. After the Action executes, the invocation could be intercepted again. Unsurprisingly, we call these objects "Interceptors."
Upvotes: 0