In Spring boot, you can configure Wrapper by connecting to the Tomcat connector. See This as an example:
@Bean public EmbeddedServletContainerFactory servletContainerFactory() { TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { AbstractProtocol protocolHandler = (AbstractProtocol) connector.getProtocolHandler(); TaskQueue taskqueue = new TaskQueue() { @Override public boolean offer(Runnable e, long timeout, TimeUnit unit) throws InterruptedException { return super.offer(new MyRunnable(e), timeout, unit); } @Override public boolean offer(Runnable o) { return super.offer(new MyRunnable(o)); } }; TaskThreadFactory tf = new TaskThreadFactory("artur-" + "-exec-", false, 0); ThreadPoolExecutor e = new ThreadPoolExecutor(10, 10, 1000, TimeUnit.SECONDS, taskqueue); taskqueue.setParent(e); protocolHandler.setExecutor(e); } }); return factory; }
And here is my custom Runable (it can be any wrapper, I didn’t bother to implement exactly yours):
static class MyRunnable implements Runnable { private Runnable r; public MyRunnable(Runnable r) { this.r = r; } @Override public void run() { System.out.println("Custom runable"); runInner(); } void runInner() { r.run(); } }
And here is my import:
import java.util.concurrent.TimeUnit; import org.apache.catalina.connector.Connector; import org.apache.coyote.AbstractProtocol; import org.apache.tomcat.util.threads.TaskQueue; import org.apache.tomcat.util.threads.TaskThreadFactory; import org.apache.tomcat.util.threads.ThreadPoolExecutor; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.PropertySource;
What does it do:
The Tomcat Connector initializes itself. You can configure the artist to use, in which case Tomcat will stop creating its own configuration and use yours instead.
By rewriting the suggestion methods in the queue, you can wrap your Runnable in any custom Runnable . In my case, for testing, I just added Sysout to make sure everything was working correctly.
The Threadpool implementation that I used is the default exact copy for tomcat (minus properties). This way, the behavior remains unchanged, except that any Runnable now your delegating shell.
When I test this, my console prints:
Custom runable
Hope this is what you were looking for.
I am using Spring boot, but this is essentially a tomcat problem, not a Spring problem. You can adapt the solution to your specific scenario.
- Arthur