On 10/9/2017 12:56 PM, Christoph Nenning wrote:
> I'd rather have just a very thin wrapper around servlet api, like so:
> - actions might be declared async, this causes struts to call
> request.startAsync()
> - applications using that must use their own threads to do work (as with
> servlet api)
> - it should still be possible to use all struts results
> - we need some mechanism for the action to trigger result execution and
> cleanup of async context (result may run in application managed thread as
> well)
> 
> 
> This would mean there is not too much and not too complicated code in
> struts. Applications which would like to use servlet api async context
> could do so and still use struts concepts like interceptors, results or
> ognl. It is up to the application to gain something of async, as it is
> with servlet api.

Yes I see. However, it seems execAndWait interceptor already can do a 
similar work. I think the lack of support is at result side and upload 
side. I thought If I define three phases: upload, action and result, and 
define S as short time and L as long time (spends process), then we have 
8 states from SSS to LLL. For example:

LLL: a lot of users want to upload video and download converted one
SSL: a lot of users want to download specific files (download server)
SLS: seems execAndWait interceptor can handle this one

I even thought I can have 16 states by defining if result is dependent 
to action or not :)

Moreover, maybe this is not as simple as it appears too, I guess. Struts 
is a filter and user may use other filters before or after. To satisfy 
servlet3, we should immediately release current thread back to container 
when async action reached, so, what we should pass as result to back 
interceptors and filters now? maybe null result and save original result 
somewhere waiting for action back but we lose thread local attached data 
:( and currently I'm not sure what happens when we execute a result in 
separate empty thread!


If @dev agree I have an idea. For first step, what do you think to 
level-up it to filter level (as it already is)? When I was playing I had 
developed a modified filter below and saw it works! (except a few 
special cases like when user has request scope spring bean). User can 
put async actions in a specific namespace then map those to this filter 
instead setting async-support to true. Below is some simple codes of 
this filter (all params can be changed to get by a filter-param):

public class StrutsExecuteFilter {
     public final int REQUEST_TIMEOUT = 240000;
     private ExecutorService exe;

     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
if(async-supported && async){
         int size = 41;
         exe = Executors.newFixedThreadPool(
                 size,
                 new ThreadFactory() {
                     public Thread newThread(Runnable r) {
                         return new Thread(r, "Struts Async Processor");
                     }
                 }
         );
}
         //Strut's current init codes
     }

     @Override
     public void doFilter(final ServletRequest req, final 
ServletResponse res, final FilterChain chain) throws IOException, 
ServletException {

         //Strut's current codes

         if (mapping == null || recursionCounter > 1) {
             boolean handled = 
execute.executeStaticResourceRequest(request, response);
             if (!handled) {
                 chain.doFilter(request, response);
             }
         } else {
             //I ADDED THESE
             final AsyncContext context = req.startAsync();
             context.setTimeout(REQUEST_TIMEOUT);

             context.addListener(new AsyncListener() {
                 public void onComplete(AsyncEvent asyncEvent) throws 
IOException {
                 }

                 public void onTimeout(AsyncEvent asyncEvent) throws 
IOException {
                     context
                             .getResponse()
                             .getWriter().write("Request Timeout");
                 }

                 public void onError(AsyncEvent asyncEvent) throws 
IOException {
                     context
                             .getResponse()
                             .getWriter().write("Processing Error");
                 }

                 public void onStartAsync(AsyncEvent asyncEvent) throws 
IOException {
                 }
             });
             exe.execute(new ContextExecution(context, mapping));
         }
     }

     @Override
     public void destroy() {
         exe.shutdown();
         //Strut's current destroy
     }

     class ContextExecution implements Runnable {

         final AsyncContext context;
         ActionMapping mapping;

         public ContextExecution(AsyncContext context, ActionMapping 
mapping) {
             this.context = context;
             this.mapping=mapping;
         }

         public void run() {
             try {
                 execute.executeAction((HttpServletRequest) 
context.getRequest(),
                         (HttpServletResponse) context.getResponse(), 
mapping);

                 context.complete();
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
}

:) I love it

Sincerely Yours,
Yasser.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@struts.apache.org
For additional commands, e-mail: dev-h...@struts.apache.org

Reply via email to