Exposing Hibernate and Ehcache statistics through JMX

When monitoring an JEE application with Java Persistence it’s useful to expose some statistics via JMX. If you’re using the common combination of Spring, Hibernate and Ehcache as 2nd level cache, you can achieve that by adding a few lines to your Spring context.

Suppose that you have an EntityManagerFactory configuration with a singleton Ehcache such like this one:

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="persistenceUnitName" value="myPersistenceUnit"
  <property name="jpaVendorAdapter">
    <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
    </bean>
  </property>
  <property name="jpaProperties">
    <props>
      <prop key="hibernate.generate_statistics">true</prop>
      <!-- Activate 2n level cache -->
      <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
      <prop key="hibernate.cache.use_second_level_cache">true</prop>
      <prop key="hibernate.cache.use_query_cache">true</prop>
      <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>				
    </props>
  </property>
</bean>

Then you can expose the Hibernate and the Ehache statistics by adding this snippet to your configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:mbean-server />

	<bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter">
		<property name="beans">
			<map>
				<entry key="MyApp:name=hibernateStatisticsMBean" value-ref="hibernateStatisticsMBean" />
				<entry key="MyApp:name=ehCacheManagerMBean" value-ref="ehCacheManagerMBean" />
			</map>
		</property>
	</bean>

	<bean name="hibernateStatisticsMBean" class="org.hibernate.jmx.StatisticsService">
		<property name="sessionFactory" value="#{entityManagerFactory.getSessionFactory()}" />
	</bean>

	<bean name="ehCacheManagerMBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
		<property name="shared" value="true" />
	</bean>
</beans>

The get the native Hibernate SessionFactory from the entityManagerFactory I’ve used Spring Expression Language support (line 19).

When you now launch jconsole or jvisualvm you should be able to see your beans in the MBeans section:

Load JPA Entites from within multiple projects

The recently released Spring 3.1 opens up the possibility to scan the whole classpath for JPA entities. The idea is to bootstrap JPA programmatically without a persistence.xml file. You can find details about the new feature here: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/new-in-3.1.html#new-in-3.1-jpa-without-xml

Instead of referring to a persistence unit you can simply define the Java packages containing your entity files, when creating a LocalContainerEntityManagerFactoryBean. And the whole classpath is scanned.

 highlight="3,6"]
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="packagesToScan">
    <array>
      <value>at.nonblocking.test.model<value>
      <value>at.nonblocking.test2.**.model<value>
    <array>
  <!-- <property name="persistenceUnitName" value="myPersistenceUnit" /> -->
  <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
      <property name="generateDdl" value="true" />
      <property name="showSql" value="true" />
    </bean>
  </property>
</bean>

And even wildcards are possible!