Hi,

On Tomcat 9.0.12, what is the recommended way of having HTTP requests sent to a 
certain URL pattern be processed on a separate threadpool from all other 
requests?


I have found that the HTTP Connectors can only be configured with one executor, 
therefore all requests always get processed on that single executor.


I tried to implement a Filter that takes advantage of Servlet 3.0 async 
processing to delegate processing the remaining filterChain to a separate 
executor, but have found that the filterChain is released after the main thread 
finishes, and therefore is not usable on the downstream thread pool.

For example:

public class SeparateThreadPoolFilter implements Filter {
    
    private static final Logger logger = 
LoggerFactory.getLogger(SeparateThreadPoolFilter.class);
    
    private final Executor executor;

    public SeparateThreadPoolFilter(Executor executor) {
        this.executor = executor;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain)
            throws IOException, ServletException {
        
        AsyncContext asyncContext = request.startAsync();
        
        executor.execute(() -> {
            try {
                // This chain is no longer usable, because it is released in 
the main thread after doFilter returns
                chain.doFilter(request, response);
            } catch (IOException | ServletException e) {
                logger.error("Exception occurred while executing HTTP request 
on separate threadpool" + e);
            } finally {
                asyncContext.complete();
            }
        });
    }

}

I have configured this as the first filter in the chain for the the desired url 
patterns.  I create and register this filter programmatically, and pass the 
desired Executor into the constructor.

What I have observed is that after doFilter returns, Tomcat will release the 
filterChain here...

https://github.com/apache/tomcat/blob/acaeccf3df95b24904c5f0ca9dd0f553d8f43289/java/org/apache/catalina/core/StandardWrapperValve.java#L254

Releasing the filter chain makes it unusable, since it removes all the filters, 
and the servlet...

https://github.com/apache/tomcat/blob/acaeccf3df95b24904c5f0ca9dd0f553d8f43289/java/org/apache/catalina/core/ApplicationFilterChain.java#L295-L306

Therefore, a NullPointerException occurs within ApplicationFilterChain when it 
tries to invoke the servlet (which is now null)...

Exception in thread "worker-11" java.lang.NullPointerException
    at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at 
com.example.SeparateThreadPoolFilter.lambda$0(SeparateThreadPoolFilter.java:34)


So my questions are:
1) Is there another way of delegating processing of certain url patterns to a 
separate threadpool?
2) Is this a bug?  i.e. should filterChains still be usable after doFilter 
returns if request.startAsync() has been called?

Thank you,

Phil

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

Reply via email to