Using AbstractSpringContextJmxServiceDaemon to dependency inject a daemon
Subscribe

From OpenNMS

Jump to: navigation, search

Contents

Components

Add an entry for the daemon to beanRefContext.xml

Reference: beanRefContext.xml

The beanRefContext.xml file doesn't list the Spring beans that create daemons, but it instead lists the application contexts used by each daemon. You'll see that every daemon that has been Springified has an application context defined in the beanRefContext.xml file for the Maven project it is in. There are many common elements to some or all daemons, so we have defined a handful of parent application contexts, and every daemon application context should extend one of them:

daoContext 
DAOs
daemonContext 
daoContext, plus an eventIpcManager
commonContext 
daemonContext, plus some reused configuration file managers/factories/DAOs

You'll probably add an entry that looks like this:

<bean id="queuedContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
  <constructor-arg>
    <list>
      <value>META-INF/opennms/applicationContext-queued.xml</value>
    </list>
  </constructor-arg>
  <constructor-arg ref="daemonContext" />
</bean>

Change "queuedContext" and "applicationContext-queued.xml" to something appropriate for your daemon. You'll create the applicationContext-<daemon>.xml file in the next step.

Create an applicationContext-<daemonName>.xml file

Example: applicationContext-statisticsDaemon.xml

This is a Spring beans file that will define your daemon and all of the beans that are injected into your daemon but not shared (beans that are used outside of your daemon should be defined elsewhere). The only constraint is that the bean name for the main daemon class *must* be called "daemon" and the class *must* implement the SpringServiceDaemon interface as well as the standard Spring InitializingBean interface. See the last section on this page for details.

Create a JMX MBean interface for your daemon, ideally extending BaseOnmsMBean

Reference: BaseOnmsMBean source Example: StatsdMBean source

I'm not even sure if this needs to be done, but I haven't tested to see if it can be skipped.

We need a JMX MBean interface that we will implement later. If your daemon just needs basic init/start/stop/status, then the BaseOnmsMBean has all you need and your own JMX MBean class just extend BaseOnmsMBean and otherwise be empty. If you need to expose other methods, such as detail status or statistics methods, you'll need to add those here, but you should still extend BaseOnmsMBean anyway.

Create a JMX class that extends AbstractSpringContextJmxServiceDaemon and implements your JMX MBean interface

Reference: AbstractSpringContextJmxServiceDaemon source Example: Statsd (JMX) source

In most cases, this will only have two methods: getLoggingPrefix to return the default Log4J logging prefix for this daemon and getSpringContext to return the name of the Spring application context that defines this daemon (this is the "<daemon name>Context" name that you defined in the first step in beanRefContext.xml). If you defined any additional methods in your JMX MBean class, you'll have to implement them here. You can use the getDaemon method from AbstractSpringContextJmxServiceDaemon to get your daemon class from Spring, such as if you need to get statistics from the daemon.

Create your daemon class that extends SpringServiceDaemon

Reference: SpringDaemonService source Example: Statsd source

This is where the real work is done. Your daemon class will be created by Spring (this is the "daemon" bean you defined in applicationContext-<daemon>.xml) and dependency injected according to the configuration you specified. Your daemon class must implement both the InitializingBean and SpringServiceDaemon interfaces, which will require you to have an afterPropertiesSet method and a start method, respectively. afterPropertiesSet should do any final configuration checks and prepare your daemon to be started and start should actually start your daemon (e.g.: start processing threads, start listening on TCP ports, start scanning, etc.). Your bean can also optionally implement DisposableBean to cleanly shutdown threads, stop listening on TCP ports, etc. when your daemon is stopped, and this is highly encouraged (and should probably be required).