2011年8月28日 星期日

JMX & Spring

用Spring要產生一個MBean並且註冊到MBeanServer是蠻容易的。基本上,幾乎只要使用XML設定就可以了。作法如下:
  1. 確定有使用context的XML schema。在XML設定檔中加入
    <context:mbean-server id="mbeanServer">
    , 其中id是用來表示該mbean server。這個xml tag是Spring 2.5以後多的,可以簡化設定。當然也可以用傳統的spring bean的定義方式:
    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
  2. 加入RMI registry的宣告,一般來說使用JMX的remoting,在沒特別處理的情況,都是以RMI protocol來做通訊:
    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"><property name="port" value="1099"/></bean>
  3. 宣告MBean的connector server,這是用來讓外部可以連線到MBeanServer:
    <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
    <property name="threaded" value="true"/>
    <property name="objectName" value="connector:name=rmi"/>
    <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/>
    </bean>
    ,其中,service url的定義跟JMX的定義跟格式是一樣的。
  4. 最後就是宣告MBeanExporter,然後指定要export的bean跟ObjectName:
    <bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="server" ref="mbeanServer"/>
    <property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/>
    <property name="beans">
    <map>
    <entry key="heero:name=msService" value-ref="mobileSuitService"/>
    </map>
    </property>
    </bean>
而連線的方式,可以用一般標準的JMX client連線方式,或是使用Spring的方式。Spring的方式就是透過MBeanProxyFactoryBean來產生MBean的proxy。
最後,有幾點注意:
  1. mbean server的宣告,如果不是使用<context:mbean-server/>,則如果再產生mbean server發現已經有同id的server存在時,還是會繼續產生。所以可能會造成混淆。所以必須額外加上
    <property name="locateExistingServerIfPossible" value="true"/>
  2. 在實際上使用發現,如果有使用Hibernate跟Spring JMX support,則用傳統bean定義的方式產生mbean server,會一直警告該server已經存在。
  3. 經測試發現,當mbean server啟動時,立刻去連線會失敗,但是若是等待幾秒則OK
  4. 根據Spring文件,MBeanExporter是不可以lazy initialization的。所以必須設定為lazy-init="false"
這是最簡單容易的作法之一,在幾乎不改code的情況下就可以產生JMX的支援。當然Spring也有其他的作法,像是使用annotation。詳情就參考Spring文件。

Property file & Spring

Spring設定除了透過annotation跟xml之外,也可以透過property file來讀取。SpringFramework有提供這樣的機制。
首先,定義設定檔內容,例如:
(jmx.properties)
jmx.host=localhost
jmx.port=1099

然後在spring的xml設定檔內,先加入PropertyPlaceholderConfigurer的定義:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jmx.properties"/>
</bean>
其中,location是指要讀取的設定檔檔名與位置。範例中的寫法是指在classpath內找尋jmx.properties。
然後在需要使用的spring xml設定檔中,使用${property name}的方式即可。例如:
<bean id="example" class="...">
<property name="host" value="${jmx.host}"/>
<property name="port" value="${jmx.port}"/>
</bean>