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: [email protected]
For additional commands, e-mail: [email protected]