问题
I have a login screen where some user input validation will happen, the user will be authenticated and finally redirected to the welcome screen.
Below is the interceptor definition for the LoginAction:
<package name="default" extends="struts-default" namespace="/">
<interceptors>
<interceptor name="myInterceptor"
class="com.interceptor.MyInterceptor"></interceptor>
<interceptor-stack name="newStack">
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack" />
<interceptor-ref name="execAndWait">
<param name="delay">100</param>
<param name="delaySleepInterval">500</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="login"
class="com.action.LoginAction">
<interceptor-ref name="newStack"/>
<result name="success">common/Welcome.jsp</result>
<result name="wait">common/wait.jsp</result>
<result name="error">Login.jsp</result>
<result name="input">Login.jsp</result>
</action>
</package>
Below is the execute method of LoginAction:
if (isUserAuthenticated) {
// Some background processing for logging purpose
return "success";
} else {
addActionError(getText("error.login"));
return "error";
}
I am having a couple of problems with this code:
1) For an authenticated user, the wait.jsp page is getting displayed but the redirection to Welcome.jsp is not happening.
2) for an unAuthenticated user, I am getting the below exception:
java.lang.NullPointerException
at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:361)
at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:208)
at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:123)
at com.opensymphony.xwork2.ActionSupport.getText(ActionSupport.java:103)
at com.infy.action.LoginAction.execute(LoginAction.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)
at org.apache.struts2.interceptor.BackgroundProcess$1.run(BackgroundProcess.java:57)
at java.lang.Thread.run(Thread.java:662)
回答1:
execAndWaitcauses the action to be executed in a new thread.- Since
ActionContextisThreadLocal, the new thread will not get the values stored in the parent thread version ofActionContext. Every thread has a unique version ofActionContext getText()will throw a NPE when it tries to execute in the new thread because it depends onActionContext
To fix this, you need to copy the parent threads ActionContext into the execAndWait thread. You can do this by extending the BackgroundProcess class, implementing the beforeInvocation() and afterInvocation() methods, and extending ExecuteAndWaitInterceptor, implementing the getNewBackgroundProcess() method.
EXAMPLE
public class YourExecAndWaitInterceptor extends ExecuteAndWaitInterceptor {
private static final long serialVersionUID = 1L;
/**
* {@inheritDoc}
*/
@Override
protected BackgroundProcess getNewBackgroundProcess(String arg0, ActionInvocation arg1, int arg2) {
return new YourBackgroundProcess(arg0, arg1, arg2, ActionContext.getContext());
}
}
public class YourBackgroundProcess extends BackgroundProcess {
private final ActionContext context;
public YourBackgroundProcess(String threadName, ActionInvocation invocation, int threadPriority, ActionContext context) {
super(threadName, invocation, threadPriority);
this.context = context;
}
/**
* {@inheritDoc}
*/
@Override
protected void beforeInvocation() {
ActionContext.setContext(context);
}
/**
* {@inheritDoc}
*/
@Override
protected void afterInvocation() {
ActionContext.setContext(null);
}
}
回答2:
NPE is happening because the action with execAndWait interceptor is running in a separate thread and you are calling getText method which uses ActionContext. ActionContext is thread local which means that values stored in the ActionContext are unique per thread.
In order to show success page after process is over you need to refresh page time to time. In examples it is done with meta http-equiv="refresh".
<meta http-equiv="refresh" content="5;url=<s:url includeParams="all" />"/>
回答3:
The key "error.login" is not found in the resources supplied with your action or application or you have used wrong locale. That means that you have not i18n resources configured. To resolve your issue you need to create LoginAction.properties file and put the key inside it
error.login = Error login
If you are using global properties file that is not seen from your post, then add this key there.
来源:https://stackoverflow.com/questions/16692658/execandwait-interceptor-not-redirecting-to-success-page-after-waiting