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>

Tuesday, August 22, 2006

freenigma beta phase started

Finally, the public beta phase of the freenigma service started, after the launch was announced at heise.de some days ago.
The freenigma service allows you to send encrypted emails from your favorite webmail provider, so that your privacy and business secrets will be protected again, and will not be stored as plaintext on the providers servers.
You can register online and apply for an invitation to the freenigma service, or just ask here (write a comment) so that i can invite you.
The official announcement concerning the start of the beta phase you find here at the freiheit.com blog.

Heap Dump Analysis

Until now i used an IBM jdk to track down memory problems. The IBM jdks allow to create heap dumps on OutOfMemoryErrors (or with kill -3) and afterwards analyse them with the HeapAnalyzer. More information on this you find in the IBM Diagnostics Guide. There seemed to be nearly no impact on performance, why i could use this also in production environments (for a short time).

Although, in some cases it's not possible to use an IBM jdk (e.g. because some sun specific implementation is required).

Now it seems to be possible to do something similar with sun jdks: in this posting on TSS i read that you can start your jvm with -XX:+HeapDumpOnOutOfMemoryError (if it's >= 1.4.2_12 or 1.5.0_06). The produced heap dump afterwards you would analyse with HAT (Heap Analysis Tool, legacy), or the newer jhat (included in Mustang).

For now i didn't test this new feature of the sun jvm, i'll post an update when i've done this.

Some links on jhat and the OQL (Object Query Language):
What's in my Java heap?
Querying Java heap with OQL
Permanent generation analysis with OQL

References:
Alan Bateman: HeapDumpOnOutOfMemoryError option in 5.0u7 and 1.4.2_12.