25 2月 2011

Startup MX4J HttpAdaptor with Spring

我用JMX用的並不多,多半而言就是拿來控制Logger 的Level,最多加個清Cache,其餘就沒什麼特別在意的。
控制的介面用jconsole多半還過得去,部份案子還是會使用mx4j的HttpAdaptor來建立Web的操作介面,只是在使用上,要自動帶起HttpAdaptor還是有些困擾。

先看看MX4J 的HttpAdaptor,

public void start() throws IOException {
    final Logger logger = getLogger();
    if (server != null) {
         serverSocket = createServerSocket();
         .....
    } else {
        if (logger.isEnabledFor(Logger.INFO)) logger.info("Start failed, no server target server has been set");
    }
}
呼叫start()後,HttpAdaptor就可以提供Web的操作介面。
不過HttpAdaptor一開始就會先確認MBeanServer "server" 的有無,如果沒有就會寫個Log然後結束。
而這個MBeanServer什麼時候會被加進來呢?
是依JMX規格MBeanRegistration,執行preRegister()後才會帶進來,所以如果想在Spring的設定檔裡,加個init-method="start",是無法讓這個Adaptor正常提供Web操作。

那就看看Spring MBeanExporter的原始碼是如何操作MBean的Lifecycle,看到MBeanExporterLinstener這Interface,所以我們可以透過這interface讓系統自動帶起HttpAdaptor;但實際上執行有點困難,因為Spring 2.5以後提供了一個context:mbean-server,可以直接取得系統中現有的MBeanServer或是自行建立一個,所以比較無從加入MBeanExporterLinstener到MBeanServer中。

最後想想,還是從MBeanRegistration這個介面下手,所以直接extend HttpAdaptor後override postRegister()....

 

public class AutostartHttpAdaptor extends HttpAdaptor {
 
 private static final Logger logger = LoggerFactory.getLogger(AutostartHttpAdaptor.class);
 @Override
 public void postRegister(Boolean registrationDone) {
  super.postRegister(registrationDone);
  
  if (!registrationDone) {
   logger.warn("HttpAdaptor should not be invoked start() without registration success.");
   return;
  }
  
  logger.info("Post Register HttpAdaptor('"+registrationDone+"'):");

  try {
   this.start();
  } catch (IOException e) {
   logger.error("HttpAdaptor startup has been failed.", e);
  }
 }

 @Override
 public void postDeregister() {
  super.postDeregister();
  logger.info("Post Deregister HttpAdaptor():");
  this.stop();
 }
 
}

沒有留言: