Friday, June 23, 2017

How to run DelegatingSecurityContextRunnable every time when tomcat creates new Thread

Leave a Comment

I have an spring app which is using tomcat with websockets. I would like to use the DelegatingSecurityContextRunnable to be executed every time when tomcat creates a new thread, i.e. warp the tomcat thread. Does anyone know how this is done. The reason for the question can be found.here

Maybe this can be done with using AOP and some advice?

1 Answers

Answers 1

In Spring boot you can configure a Wrapper by hooking into 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 (this can be any wrapper, i did not bother implementing 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 are my imports:

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 this does:

The Tomcat connector initialises itself. You can set the executor to use, in which case Tomcat will stop creating its own configuration and instead use yours.

By overwriting the offer methods in the queue, you have the chance to wrap your Runnable in any custom Runnable. In my case, for testing, I simply added a Sysout to see that everything is working correctly.

The Threadpool implementation I used is an exact copy of the tomcat default (minus the properties). This way, behaviour stays the same, except that any Runnable is now your delegating wrapper.

When I test that, my console prints:

 Custom runable 

I hope this is what you were looking for.

I use spring boot, but this is essentially a tomcat issue not a spring issue. You can adapt the solution to your specific scenario.

-- Artur

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment