[SNMP4J] (WIP) SNMP4J CommonJ integration, second round (with Spring)

Brice Fines bfines at sermepa.es
Tue Mar 9 17:06:07 CET 2010


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" ....../>




More information about the SNMP4J mailing list