Hi Frank, Thanks for your advices. I tried to use the IBM WAS ThreadFactory code, thinking this would match what SNMP4J was expecting (a threadfactory) (and their WasTreadFactory was wrapping new threads around WorkManager threads). I switched my implementation to the one you suggested (got rid of thread wrapping, just execute things thanks to WorkManager).
I did it using TaskExecutor from Spring. This way I plug a WorkManagerTaskExecutor in my implementation for IBM WAS, but this could come handy for people using SNMP4J with JBOSS or Glassfish (since Spring provides TaskExecutor for these too). I need to make further tests, but everything seems fine so far (you were right, no more problems with thread deadlocks after shutting down). I will post if I can come up with a TimerFactory using WAS TimerManager. The ThreadFactory for Spring (I use Spring 2.5.6.SEC-01 and SNMP4J 1.10.2): import org.snmp4j.log.LogAdapter; import org.snmp4j.log.LogFactory; import org.snmp4j.util.ThreadFactory; import org.snmp4j.util.WorkerTask; import org.springframework.core.task.TaskExecutor; import org.springframework.util.Assert; /** * TreadFactory implementation based on Spring TaskExecutor. */ public class SpringTaskExecutorThreadFactoryImpl implements ThreadFactory { /** * Logger. */ final static LogAdapter LOGGER = LogFactory .getLogger(SpringTaskExecutorThreadFactoryImpl. class); /** * TaskExecutor. */ private TaskExecutor taskExecutor; /** * Establece el TaskExecutor. * * @param taskExecutor * un TaskExecutor. */ public void setTaskExecutor(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } /** * Constructor. */ public SpringTaskExecutorThreadFactoryImpl() { } /** * Constructor. * * @param taskExecutor * a task executor. */ public SpringTaskExecutorThreadFactoryImpl(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } /* * (sin Javadoc) * * @see org.snmp4j.util.ThreadFactory#createWorkerThread(java.lang.String, * org.snmp4j.util.WorkerTask, boolean) */ public WorkerTask createWorkerThread(String name, WorkerTask task, boolean daemon) { LOGGER.debug("Creating thread: " + name + " daemon: " + daemon); return new SpringTaskExecutorWorkerTaskImpl(taskExecutor, name, task, daemon); } /** * Initialization. */ public void init() { Assert.notNull(taskExecutor, "taskExecutor is null"); } } The WorkerTask : import org.snmp4j.log.LogAdapter; import org.snmp4j.log.LogFactory; import org.snmp4j.util.WorkerTask; import org.springframework.core.task.TaskExecutor; /** * WorkerTask implementation based on Spring TaskExecutor. */ public class SpringTaskExecutorWorkerTaskImpl implements WorkerTask { /** * Logger. */ final static LogAdapter LOGGER = LogFactory .getLogger(SpringTaskExecutorWorkerTaskImpl.class ); /** * TaskExecutor. */ private TaskExecutor taskExecutor; /** * Worker task. */ private WorkerTask workerTask; /** * Name. */ private String name; /** * True if daemon thread, false otherwise. */ private boolean daemon; /** * Constructor. * * @param taskExecutor * a task executor. * @param name * a name. * @param workerTask * a worker task. * @param daemon * true if daemon thread, false otherwise. */ public SpringTaskExecutorWorkerTaskImpl(TaskExecutor taskExecutor, String name, WorkerTask workerTask, boolean daemon) { this.taskExecutor = taskExecutor; this.name = name; this.workerTask = workerTask; this.daemon = daemon; } /* * (withoutJavadoc) * * @see org.snmp4j.util.WorkerTask#interrupt() */ public void interrupt() { LOGGER.debug("Thread interrupt: " + this.name); // do nothing } /* * (withoutJavadoc) * * @see org.snmp4j.util.WorkerTask#join() */ public void join() throws InterruptedException { LOGGER.debug("Thread join: " + this.name); // do nothing } /* * (withoutJavadoc) * * @see org.snmp4j.util.WorkerTask#terminate() */ public void terminate() { LOGGER.debug("Thread terminate: " + this.name); // do nothing } /* * (withoutJavadoc) * * @see java.lang.Runnable#run() */ public void run() { LOGGER.debug("Thread run: " + this.name); taskExecutor.execute(workerTask); } } My application context looks like: <bean id="taskExecutor" class= "org.springframework.scheduling.commonj.WorkManagerTaskExecutor" p:workManagerName="wm/your_wm_name" p:resourceRef="true" /> <bean id="snmp4jThreadFactory" class= "xx.xxxxxxx.xxxxx.snmp4j.util.SpringTaskExecutorThreadFactoryImpl" init-method="init" p:taskExecutor-ref="taskExecutor" /> <bean id="snmp4jConfigurator" class="xx.xxxxxxx.xxxxx.snmp4j.util.Snmp4jConfigurator" init-method="init" p:threadFactory-ref= "snmp4jThreadFactory" /> The associated WorkManager has a growable pool of thread (to handle big amount of SNMP commands and TRAP (I also use WorkManager threads for TRAP processing)). Snmp4jConfigurator is a simple class in charge of calling SNMP4JSettings.setThreadFactory(threadFactory); with the injected threadFactory (and with the injected TimerFeactory in a near future I hope :-) ). Next, I make sure Snmp4jConfigurator is called first by defining dependencies between Spring beans: <bean id="yourSnmpChannel" class="xx.xxxxxxx.xxxxx.business.snmp.SnmpChannel" depends-on="snmp4jConfigurator" ....../> _______________________________________________ SNMP4J mailing list SNMP4J@agentpp.org http://lists.agentpp.org/mailman/listinfo/snmp4j