[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