I have a Struts2 application that has an action that can take anywhere between 1 sec to 5 mins to run. So, I'm using the execAndWait interceptor to display a wait page if the action takes more than 20 secs to run. The setup of the action looks like this:
<action name="myAction" class="myActionClass">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="execAndWait">
<param name="delay">20000</param>
</interceptor-ref>
<result name="success">myPage.jsp</result>
<result name="wait">waitPage.jsp</result>
</action>
I have tested this with a scenario where the action just takes 1 second to run. I expected that the wait page will never be shown.
However, the wait page still showed up. I tried debugging my action class and method and found that the execution hangs at this statement below for the time specified in the
<param name="delay">
In this case, it waits for 20 secs at the statement below and then completes execution successfully.
getSession().put(A_SESSION_VARIABLE, 10);
Note: MyActionClass does implement SessionAware
Has anyone else experienced this problem? Is there a work around for this?
A workaround (if your action is used in a servlet environment): implement ServletRequestAware interface and use HttpServletRequest to get session.
request.getSession().setAttribute(A_SESSION_VARIABLE, 10);
I have a different approach for this problem. You can run the heavy processing in a separate thread and return the response to the user instantly stating that the work is in progress. When the work is finished you can return whatever you want to return to the user. This can be achieved by using polling.
In the meantime user don't have to wait and can do other stuff.
Hope it helps.
Related
Through a recent debugging session I realized that when refreshing a "wait" page during an ExecuteAndWait process, it calls the action's prepare() and validate() methods each time. For some reason I thought Struts would immediately identify the "waiting" Action, and if it wasn't finished, it would immediately return a WAIT result with the running Action at the top of the stack. I now realize since the ExecuteAndWait interceptor is at the end of the interceptor stack - so it obviously doesn't send the WAIT result until all interceptors have been executed.
That said, in some of my long running actions, the prepare() method hits the database for some rather resource heavy database queries. So if I have an ExecuteAndWait page showing the progress status of an Action (refreshing every 2 seconds in my case), this seems incredibly inefficient. Is there a way to avoid this? Am I setting up my Action logic flow incorrectly?
A sample of one of my Action setups in struts.xml:
<action name="ContactDelete" class="com.afs.web.struts.action.contact.ContactDeleteAction">
<interceptor-ref name="myParamsPrepareParamsStack" />
<result>/struts/contact/contactDelete_modal.jsp</result>
<result name="error">/struts/common/error/error_modal.jsp</result>
<result name="login">/struts/common/login/login_modal.jsp</result>
</action>
<action name="ContactDelete_delete" class="com.afs.web.struts.action.contact.ContactDeleteAction" method="delete">
<interceptor-ref name="myDefaultStack"/>
<interceptor-ref name="openSessionExecuteAndWaitInterceptor" >
<param name="delay">0</param>
</interceptor-ref>
<result name="input">/struts/contact/contactDelete_modal.jsp</result>
<result name="wait">/struts/common/progressMonitorWait_modal.jsp</result>
<result>/struts/common/progressMonitorSuccess_modal.jsp</result>
<result name="error">/struts/common/error/error_modal.jsp</result>
<result name="login">/struts/common/login/login_modal.jsp</result>
</action>
I have the following code in struts.xml and I want that the result for "success" will be in a new page, is there way to handle this in struts.xml?
<action name="deleteAccount" class = "com.sample.AccountMaintenanceAction" method="deleteAccount" >
<result name="success">/message.jsp</result>
<result name="input" >/accountMaintenance.jsp</result>
<result name="error">/accountMaintenance.jsp</result>
</action>
No; you can't open a new window from the server side.
Nor would it seem reasonable to do so if you're just trying to display a response message: seems like it'd be better to make an Ajax request and process either a JSON or HTML response.
Im trying to make it so that once i submit this form i cannot hit the back button, but with the current configuration I cannot even get the page/form to load. I can't seem to figure out why "invalid.token" is always being triggered thus redirecting me to index.jsp no matter what I have the token tag in my form like im supposed to. If i use the "excludeMethods" filter and exclude View then my page loads but I can hit the back button freely so it still does not work properly. I have tried moving the interceptor-ref above and below my noLoginStack but it dosen't make a difference. Based on my debugging my actual java class isn't even being hit, so its failing before then. What am I doing wrong?
My action declaration:
<action name="viewAppointmentLetter" class="edu.ucr.c3.rsummer.controller.instructor.ManageAppointmentLetters">
<interceptor-ref name="noLoginStack"/>
<interceptor-ref name="token" />
<result name="invalid.token">/index.jsp</result>
<result name="error" type="redirectAction">index.do</result>
<result name="input">/instructor/assigned_appts.jsp</result>
<result name="view">/instructor/assigned_appts.jsp</result>
<result type="redirectAction">index.do</result>
</action>
My assigned_appts.jsp:
<s:form action="saveAppointmentLetter" onsubmit="return verifySubmit();">
<s:token name="token" />
.....
</s:form>
If its any clue I always get this in my console
WARN org.apache.struts2.util.TokenHelper - Could not find token name in params.
In struts2 the order of interceptor is very important. you should follow this order.
<interceptor-ref name="token"/>
<interceptor-ref name="noLoginStack"/>
USe TokenSession interceptor.Had to handle result by result name="invalid.token" in struts.xml in specific action.
The page from which your action is generated at that page you have to write <s:token> tag in the header
I use Token Session to prevent duplicate form submits, but the first time I make a request to server, I always get error page
<action name="show" class="ClientAction">
<interceptor-ref name="tokenSession" />
<interceptor-ref name="basicStack" />
<result name="invalid.token">/WEB-INF/error.jsp</result>
result type="tiles" name="success">page.view</result>
</action>
"<s:token />" was added to may success page between <s:form> and </s:form>, but it doesn't run correctly.
plz help me to solve them, is there another way prevent duplicate form submits. I wait for suggestion, thank u very much. : )
It seems that you are not using proper interceptor name. If you want to use the session token, it is token-session.
try using token-session instead of tokenSession.
Hope that helps.
tag <s:token /> must be inserted into form which is double-submitted, not into success form. If token tag is missing, interceptor resolve the submitted request as invalid even if it's the first attempt.
I am not sure if this is me or if this is a bug.
I got the following error
11:52:01,623 ERROR ObjectFactory:27 - Unable to set parameter [dest] in result of type [org.apache.struts2.dispatcher.ServletRedirectResult]
Caught OgnlException while setting property 'dest' on type 'org.apache.struts2.dispatcher.ServletRedirectResult'. - Class: ognl.ObjectPropertyAccessor
File: ObjectPropertyAccessor.java
Method: setProperty
Line: 132 - ognl/ObjectPropertyAccessor.java:132:-1
at com.opensymphony.xwork2.ognl.OgnlUtil.internalSetProperty(OgnlUtil.java:392)
And my config is pretty minimal
<package name="esupport" namespace="/esupport" extends="struts-default">
<action name="old-esupport" class="com.my.MyRedirectAction">
<result type="redirect">
<param name="location">http://some.server.com/init.asp</param>
<param name="dest">${dest}</param>
</result>
</action>
</package>
And my class has a pair of get/set method. And that's it. Nothing Fancy
I have found this thread in the forum. But it doesn't solve my problem
I am using
Struts 2.1.16
Spring 2
Spring Security + CAS
(The funny behavior is it sends me to the CAS server after the error, but I guess it will be corrected after the redirect issue got fixed)
it seems like a bug with Struts2. they recommend...hiding the error by:
<category name="com.opensymphony.xwork2.ObjectFactory">
<priority value="fatal"/>
</category>
from....TroubleShooting guide section on redirects
I faced this issue after deploying the application in WAS 7 server. It was an existing application and there was no code change.
Found the following exceptions in the server start-up logs
Failed to write out object: ext___405722372
com.ibm.wkplc.extensionregistry.util.XmlUtilException: Unable to write to the given file
Just cleared the server cache and restarted it and the issue got resolved.