22
22
import com .opensymphony .xwork2 .ActionContext ;
23
23
import com .opensymphony .xwork2 .ActionInvocation ;
24
24
import com .opensymphony .xwork2 .ActionProxy ;
25
+ import com .opensymphony .xwork2 .config .entities .ResultConfig ;
25
26
import com .opensymphony .xwork2 .inject .Container ;
26
27
import com .opensymphony .xwork2 .inject .Inject ;
27
28
import com .opensymphony .xwork2 .interceptor .MethodFilterInterceptor ;
28
29
import org .apache .logging .log4j .LogManager ;
29
30
import org .apache .logging .log4j .Logger ;
30
31
import org .apache .struts2 .ServletActionContext ;
32
+ import org .apache .struts2 .interceptor .exec .BackgroundProcess ;
33
+ import org .apache .struts2 .interceptor .exec .ExecutorProvider ;
34
+ import org .apache .struts2 .interceptor .exec .StrutsBackgroundProcess ;
35
+ import org .apache .struts2 .interceptor .exec .StrutsExecutorProvider ;
31
36
import org .apache .struts2 .util .TokenHelper ;
32
37
import org .apache .struts2 .views .freemarker .FreemarkerResult ;
33
38
84
89
* <!-- END SNIPPET: description -->
85
90
*
86
91
* <p><u>Interceptor parameters:</u></p>
87
- *
92
+ * <p>
88
93
* <!-- START SNIPPET: parameters -->
89
94
*
90
95
* <ul>
94
99
* <li>delaySleepInterval (optional) - only used with delay. Used for waking up at certain intervals to check if the background process is already done. Default is 100 millis.</li>
95
100
*
96
101
* </ul>
97
- *
102
+ * <p>
98
103
* <!-- END SNIPPET: parameters -->
99
104
*
100
105
* <p><u>Extending the interceptor:</u></p>
101
- *
106
+ * <p>
102
107
* <!-- START SNIPPET: extending -->
103
108
* <p>
104
109
* If you wish to make special preparations before and/or after the invocation of the background thread, you can extend
167
172
* <result name="success">longRunningAction-success.jsp</result>
168
173
* </action>
169
174
* </pre>
170
- *
175
+ * <p>
171
176
* <!-- END SNIPPET: example -->
172
- *
173
177
*/
174
178
public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
175
179
@@ -186,30 +190,35 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
186
190
private int threadPriority = Thread .NORM_PRIORITY ;
187
191
188
192
private Container container ;
193
+ private ExecutorProvider executor ;
189
194
190
195
@ Inject
191
196
public void setContainer (Container container ) {
192
197
this .container = container ;
193
198
}
194
199
200
+ @ Inject (required = false )
201
+ public void setExecutorProvider (ExecutorProvider executorProvider ) {
202
+ this .executor = executorProvider ;
203
+ }
204
+
195
205
/**
196
206
* Creates a new background process
197
207
*
198
- * @param name The process name
208
+ * @param name The process name
199
209
* @param actionInvocation The action invocation
200
- * @param threadPriority The thread priority
210
+ * @param threadPriority The thread priority
201
211
* @return The new process
202
212
*/
203
213
protected BackgroundProcess getNewBackgroundProcess (String name , ActionInvocation actionInvocation , int threadPriority ) {
204
- return new BackgroundProcess ( name + "BackgroundThread" , actionInvocation , threadPriority );
214
+ return new StrutsBackgroundProcess ( actionInvocation , name + "_background-process" , threadPriority );
205
215
}
206
216
207
217
/**
208
218
* Returns the name to associate the background process. Override to change the way background processes
209
219
* are mapped to requests.
210
220
*
211
221
* @param proxy action proxy
212
- *
213
222
* @return the name of the background thread
214
223
*/
215
224
protected String getBackgroundProcessName (ActionProxy proxy ) {
@@ -223,10 +232,10 @@ protected String doIntercept(ActionInvocation actionInvocation) throws Exception
223
232
ActionProxy proxy = actionInvocation .getProxy ();
224
233
String name = getBackgroundProcessName (proxy );
225
234
ActionContext context = actionInvocation .getInvocationContext ();
226
- Map session = context .getSession ();
235
+ Map < String , Object > session = context .getSession ();
227
236
HttpSession httpSession = ServletActionContext .getRequest ().getSession (true );
228
237
229
- Boolean secondTime = true ;
238
+ Boolean secondTime = true ;
230
239
if (executeAfterValidationPass ) {
231
240
secondTime = (Boolean ) context .get (KEY );
232
241
if (secondTime == null ) {
@@ -250,25 +259,30 @@ protected String doIntercept(ActionInvocation actionInvocation) throws Exception
250
259
}
251
260
252
261
if ((!executeAfterValidationPass || secondTime ) && bp == null ) {
253
- bp = getNewBackgroundProcess (name , actionInvocation , threadPriority );
262
+ bp = getNewBackgroundProcess (name , actionInvocation , threadPriority ). prepare () ;
254
263
session .put (KEY + name , bp );
264
+ if (executor .isShutdown ()) {
265
+ LOG .warn ("Executor is shutting down, cannot execute a new process" );
266
+ return actionInvocation .invoke ();
267
+ }
268
+ executor .execute (bp );
255
269
performInitialDelay (bp ); // first time let some time pass before showing wait page
256
270
secondTime = false ;
257
271
}
258
272
259
273
if ((!executeAfterValidationPass || !secondTime ) && bp != null && !bp .isDone ()) {
260
274
actionInvocation .getStack ().push (bp .getAction ());
261
275
262
- final String token = TokenHelper .getToken ();
263
- if (token != null ) {
264
- TokenHelper .setSessionToken (TokenHelper .getTokenName (), token );
276
+ final String token = TokenHelper .getToken ();
277
+ if (token != null ) {
278
+ TokenHelper .setSessionToken (TokenHelper .getTokenName (), token );
265
279
}
266
280
267
- Map results = proxy .getConfig ().getResults ();
281
+ Map < String , ResultConfig > results = proxy .getConfig ().getResults ();
268
282
if (!results .containsKey (WAIT )) {
269
- LOG .warn ("ExecuteAndWait interceptor has detected that no result named 'wait' is available. " +
270
- "Defaulting to a plain built-in wait page. It is highly recommend you " +
271
- "provide an action-specific or global result named '{}'." , WAIT );
283
+ LOG .warn ("ExecuteAndWait interceptor has detected that no result named 'wait' is available. " +
284
+ "Defaulting to a plain built-in wait page. It is highly recommend you " +
285
+ "provide an action-specific or global result named '{}'." , WAIT );
272
286
// no wait result? hmm -- let's try to do dynamically put it in for you!
273
287
274
288
//we used to add a fake "wait" result here, since the configuration is unmodifiable, that is no longer
@@ -286,7 +300,7 @@ protected String doIntercept(ActionInvocation actionInvocation) throws Exception
286
300
session .remove (KEY + name );
287
301
actionInvocation .getStack ().push (bp .getAction ());
288
302
289
- // if an exception occured during action execution, throw it here
303
+ // if an exception occurred during action execution, throw it here
290
304
if (bp .getException () != null ) {
291
305
throw bp .getException ();
292
306
}
@@ -369,5 +383,17 @@ public void setExecuteAfterValidationPass(boolean executeAfterValidationPass) {
369
383
this .executeAfterValidationPass = executeAfterValidationPass ;
370
384
}
371
385
386
+ @ Override
387
+ public void init () {
388
+ super .init ();
389
+ if (executor == null ) {
390
+ executor = new StrutsExecutorProvider ();
391
+ }
392
+ }
372
393
394
+ @ Override
395
+ public void destroy () {
396
+ super .destroy ();
397
+ executor .shutdown ();
398
+ }
373
399
}
0 commit comments