Struts2 ExecAndWait NullPointerException

2020-05-05 04:37发布

问题:

I have used ExecuAndWait in Struts2

I am getting error NPE while setting attribute in request in action(which is long running)

Here is stack track:

java.lang.NullPointerException
    at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1563)
    at org.apache.catalina.connector.Request.setAttribute(Request.java:1554)
    at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:542)
    at javax.servlet.ServletRequestWrapper.setAttribute(ServletRequestWrapper.java:239)
    at com.os.gfnactions.SiteAction.createSite(SiteAction.java:1298)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)
    at com.os.interceptor.BackgroundProcess$1.run(BackgroundProcess.java:60)
    at java.lang.Thread.run(Unknown Source)

Source snipate :

Action class:

public String createSite() throws Exception
    {
        ----

        HttpServletRequest request = ServletActionContext.getRequest();
        request.setAttribute("test", "test"); {At this line I got error}
        ---
    }

From ExecuteAndWaitInterceptor.java

231            if ((!executeAfterValidationPass || secondTime) && bp == null) {
232                bp = getNewBackgroundProcess(name, actionInvocation, threadPriority);
233                session.put(KEY + name, bp);
234                performInitialDelay(bp); // first time let some time pass before showing wait page
235                secondTime = false;
236            }

From BackgroundProcess.java

public More ...BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority) {
50         this.invocation = invocation;
51         this.action = invocation.getAction();
52         try {
53             final Thread t = new Thread(new Runnable() {
54                 public void More ...run() {
55                     try {
56                         beforeInvocation();
57                         result = invocation.invokeActionOnly();
58                         afterInvocation();
59                     } catch (Exception e) {
60                         exception = e;
61                     }
62 
63                     done = true;
64                 }
65             });
66             t.setName(threadName);
67             t.setPriority(threadPriority);
68             t.start();
69         } catch (Exception e) {
70             exception = e;
71         }
72     }

Concept of Struts2 ExecuteAndWait Whenever there is a long-running request, it going to execute in separate thread and result return WAIT, So again client resubmit the same request in some interval to know the status of its process(which is running in the thread)

My Problem: In above case when main request(Which initiate thread to invoke action) return with WAIT and again other request come to know status of action at this time in my action class I have request.setAttribute("test", "test");, at this line it throws an error which I have mention above.

回答1:

I had a similar problem with execAndWait interceptor throwing NPE. You can find my case study here: execAndWait interceptor not working with validation on how I solved this problem.. In this problem what I find out was, that execAndWait runs in separate thread and keeps throwing wait until action is completed and in mean time it cycles itself. I faced this problem, because I used model driven interceptor with it. Due to that the getModel() of model driven interceptor was repeatedly being called by execAndWait interceptor. In getModel method, it was setting the new POJO object again and again from scratch.

And then it was entering into validate method for validation. Inside validation process it found one of the POJO field to be null. Obviously, it happened due to re-creating of raw new POJO object in getModel. And thus was throwing Null Pointer Exception.

So what I did was I used SessionAware interface. And stored the POJO object for the first time when it entered validate. Because execAndWait will surely call all methods again and re-write an object from scratch. For this purpose I checked the availability of that object in getModel() method. If that found in session, then return that same object, rather of creating a new object.

I hope you'll find a way from this.