When using ExecuteAndWait, how to avoid prepare() and validate() methods on each refresh? - struts2

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>

Related

struts2 tokensession not setting request in Action excludedMethod [duplicate]

This question already has an answer here:
Prevent same action called twice as long as user is in current session
(1 answer)
Closed 5 years ago.
I'm trying to avoid double-submit problems using tokenSession. My action methods are working fine without tokenSession technique.
I add <s:token/> in upsert_crypto_sources.jsp and tokenSession interceptor in struts.xml but I receive request as null in my action excludedMethod of list().
The list page doesn't need to avoid double submit problem but if I add <s:token/> in view_crypto_sources_list.jsp and remove list() from excludedMethod then I always receive result invalid.token.
My struts.xml is like:
<struts>
<package name="key-manager" namespace="/shared/km" extends="console-default" strict-method-invocation="true">
<action name="manage_cs_*" method="{1}" class="console.shared.km.ASC_ManageCryptoProfilesAction">
<interceptor-ref name="tokenSession">
<param name="excludeMethods">
list, initInsert, load, delete
</param>
</interceptor-ref>
<result name="list">/shared/km/view_crypto_sources_list.jsp</result>
<result name="insert">/shared/km/upsert_crypto_sources.jsp</result>
<result name="update">/shared/km/upsert_crypto_sources.jsp</result>
<result name="load">/shared/km/upsert_crypto_sources.jsp</result>
<allowed-methods>list, insert, load, update, delete, testConnection, forward, cancel</allowed-methods>
</action>
My action implements ServletRequestAware interface therefore it gets the request member variable set using setServletRequest() method.
I added a defaultStack interceptor and it is working fine:
<struts>
<package name="key-manager" namespace="/shared/km" extends="console-default" strict-method-invocation="true">
<action name="manage_cs_*" method="{1}" class="console.shared.km.ASC_ManageCryptoProfilesAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="tokenSession">
<param name="excludeMethods">
list, initInsert, load, delete
</param>
</interceptor-ref>
<result name="list">/shared/km/view_crypto_sources_list.jsp</result>
<result name="insert">/shared/km/upsert_crypto_sources.jsp</result>
<result name="update">/shared/km/upsert_crypto_sources.jsp</result>
<result name="load">/shared/km/upsert_crypto_sources.jsp</result>
<allowed-methods>list, insert, load, update, delete, testConnection, forward, cancel</allowed-methods>
</action>

How to redirect with parameter

<action name="AddedPaid" class="iland.payment.SupplierPaidAction" method="insert">
<result name="success" type="redirect">ShowPaid</result>
<result name="input">/pages/payment/addToPay.jsp</result>
<result name="login">/pages/login.jsp</result>
</action>
<action name="ShowPaid" class="iland.payment.SupplierPaidAction" method="fetchAllByfk">
<result name="success">/pages/paid/showPaidDetails.jsp</result>
<result name="input">/pages/payment/ShowPay.jsp</result>
<result name="login">/pages/login.jsp</result>
</action>
Here AddedPaid Action is used to add form data in to database.
After adding data in to database I am redirecting result to ShowPaid action.
This is working properly.
Now I want whenever I redirect AddedPaid action to ShowPaid.
ShowPaid must show data of perticular supplierPaymentId for which I have added data in AddedPaid.
After redirect it is howing url
http://localhost:8082/ClothStore/ShowPaid
I want
http://localhost:8082/ClothStore/ShowPaid?supplierPaymentId=4
It's strange, usually people have 2 and want 1 :)
Btw, since you are using PostRedirectGet, you need to manually pass the parameter in Struts configuration.
Assuming you have a variable named supplierPaymentId with getter and setter, it's achievable like follows:
<action name="AddedPaid" class="iland.payment.SupplierPaidAction" method="insert">
<result name="success" type="redirectAction">
<param name="actionName">ShowPaid</param>
<param name="supplierPaymentId">${supplierPaymentId}</param>
</result>
<result name="input">/pages/payment/addToPay.jsp</result>
<result name="login">/pages/login.jsp</result>
</action>
Also use redirectAction instead of redirect, that is meant to be used to redirect to external URLs or non-Action URLs
First of all use redirectAction result instead of redirect to redirect to another action.
And use param tag to add parameters in your result configuration.
<result type="redirectAction">
<param name="actionName">ShowPaid</param>
<param name="supplierPaymentId">${supplierPaymentId}</param>
</result>
Note you need to have getter/setter for supplierPaymentId in your action class.

Struts 2 Double form submit - why?

I have a few simple actions:
<action name="edit" class="EditAction">
<result>/WEB-INF/jsp/form.jsp</result>
</action>
<action name="preview" class="PreviewAction">
<result>/WEB-INF/jsp/preview.jsp</result>
<result name="input">/WEB-INF/jsp/form.jsp</result>
</action>
<action name="store" class="StoreAction">
<result>/WEB-INF/jsp/confirmation.jsp</result>
<result name="input">/WEB-INF/jsp/preview.jsp</result>
</action>
<global-results>
<result name="invalid.token">/WEB-INF/jsp/invalidToken.jsp</result>
</global-results>
and classic scenario: user interacts with text inputs, press Save, view a Preview page and press Save on it to save data, without double-press buttons, refreshing page etc.
Why double submit can occurs in such situation?
Even I had double form submit problem in struts2 on browser refresh. I resolved the problem using post-redirect-get pattern to avoid double or duplicate form submissions. It happens because hitting "refresh page" for a reponse based on a POST request will re-issue the POST request.It repeats what you did to reach current page even for double button press. It happens for both success and error in struts2.
I suggets you to make this change where-ever necessary.
<action name="onStoreRedirect">
<result name="success" type="redirect">store</result>
</action>
<action name="store" class="StoreAction">
<result>/WEB-INF/jsp/confirmation.jsp</result>
<result name="input">/WEB-INF/jsp/preview.jsp</result>
</action>

Is there a way to declare a action result?

I have this exact same line in 5 places in my struts xml -
<result name="error" type="json"><param name="root">response</param></result>
Is there a way i can declare this as some sort of custom result and include it in the 5 places i'm using it?
You dont have to use it at multiple places instead define this as global result.
<global-results>
<result name="error" type="json">
<param name="root">response</param>
</result>
</global-results>
So when your action will return error it will use this result from the global result and use it.
But if you want something like
<action name="someaction" class="somepackage.someAction">
<result name="error" type="json">ReferSomeOhterResult</result>
</action>
this is not possible, you can only chain, redirect to a different action but one result cannot refer to another result.

Struts2 token interceptor always fails

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

Resources