magrokosmos

Thursday, August 24, 2006

JMXtend your Spring application...

...with both own annotated beans and Hibernates StatisticsService.

I just managed to export an annotation based (Spring managed) bean to JMX. This is fairly simple and can even be done using the "autodetection" mechanism of springs MBeanExporter.

The following snipplet shows the relevant part of the applicationContext.xml:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler">
<!-- will create management interface using annotation metadata -->
<bean class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="namingStrategy">
<!-- will pick up ObjectName from annotation -->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="autodetect" value="true"/>
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

The java class is defined as follows:
@ManagedResource(objectName="org.company.project:name=MailService", description="Mail Service",
log=true, logFile="jmx.log", currencyTimeLimit=15, persistPolicy="OnUpdate",
persistPeriod=200, persistLocation="foo", persistName="bar")
public final class MailServiceImpl {
...
@ManagedAttribute(description="Get the number of queued mail deliveries.")
public int getCountQueuedEmails() {
return _queue.size();
}
}

This is everything one has to do to expose a Spring bean via JMX.

If you want to check if it's working just run jconsole (it's distributed with Suns jvm) and connect to the Bootstrap process.
But stop - if you're running tomcat, you should add to the catalina.sh|bat the following catalina (java) options (when you're using startup/shutdown scripts, export the variable in startup.sh|bat):
CATALINA_OPTS="-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false"

(You can also just use the JAVA_OPTS variable)

Now lets proceed and export the StatisticsService of Hibernate to JMX (also using the MBeanExporter). For this it's necessary to turn the MBeanExporters autodetection off, otherwise he would complain that the StatisticsService has no ManagedResource annotation. The formerly autodetected bean (mailService) in consequence must be declared via the beans property. After this has been changed, a new exporter (using method name based assembly) for the StatisticsService can be declared.

Then the spring configuration is the following:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler">
<!-- will create management interface using annotation metadata -->
<bean class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="namingStrategy">
<!-- will pick up ObjectName from annotation -->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
</property>
<property name="autodetect" value="false"/>
<property name="beans">
<map>
<entry key="foo1">
<ref local="mailService" />
</entry>
</map>
</property>
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

<bean id="methodNameBasedExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="org.hibernate:name=StatisticsService">
<bean class="org.hibernate.jmx.StatisticsService">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="statisticsEnabled">
<value>true</value>
</property>
</bean>
</entry>
</map>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
<property name="methodMappings">
<props>
<prop key="bean:name=StatisticsService" />
</props>
</property>
</bean>
</property>
</bean>

0 Comments:

Post a Comment

<< Home