Reputation: 1844
I'm running a java webapp (wicket 6.13) using Hibernate 4.3 and Guice 1.0
I'm trying to configure Hibernate so that I can access runtime information via the JMX framework.
I'm not using spring, can anyone indicate how I enable the JMX on hibernate 4.3 manually.
I've poked around the JmxService, JmxServiceInitiator, JmxServiceImpl, StandardServiceRegistryImpl
I've also found the following settings in AvailableSettings:
"hibernate.jmx.enabled";
"hibernate.jmx.usePlatformServer";
"hibernate.jmx.agentId";
"hibernate.jmx.defaultDomain";
"hibernate.jmx.sessionFactoryName";
I've added the jmx.enabled true setting to my hibernate.cfg.xml file but this has had no effect.
I'm still not sure how to go about this.
Any help much appreciated
Upvotes: 5
Views: 7826
Reputation: 301
My environment is Java 8, Spring Boot 1.4.0 (Spring 4.3.2 and Hibernate 5.0.9).
I grabbed the old StatisticsServiceMBean from Hibernate 3.2.7 and used it as a template to wrap the Statistics object from Hibernate 5 using JMX Annotations.
Works with the jconsole hibernate statistics plugin.
I'm sure if you're not using Spring, you can still do something similar.
So you don't have to type all this in if you are using Spring, here it is:
import javax.persistence.EntityManagerFactory;
import javax.servlet.ServletContext;
import org.hibernate.jpa.HibernateEntityManagerFactory;
import org.hibernate.SessionFactory;
import org.hibernate.stat.CollectionStatistics;
import org.hibernate.stat.EntityStatistics;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
@Component
@ManagedResource("Hibernate:application=Statistics")
public class HibernateStatisticsMBean implements InitializingBean {
@Autowired
private ServletContext servletContext;
private Statistics stats;
@Override
public void afterPropertiesSet() throws Exception {
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
EntityManagerFactory emf = (EntityManagerFactory) wac.getBean("entityManagerFactory");
SessionFactory sessionFactory = ((HibernateEntityManagerFactory) emf).getSessionFactory();
sessionFactory.getStatistics().setStatisticsEnabled(true);
this.stats = sessionFactory.getStatistics();
}
@ManagedOperation
public void clear() {
stats.clear();
}
@ManagedOperation
public EntityStatistics getEntityStatistics(String entityName) {
return stats.getEntityStatistics(entityName);
}
@ManagedOperation
public CollectionStatistics getCollectionStatistics(String role) {
return stats.getCollectionStatistics(role);
}
@ManagedOperation
public SecondLevelCacheStatistics getSecondLevelCacheStatistics(String regionName) {
return stats.getSecondLevelCacheStatistics(regionName);
}
@ManagedOperation
public QueryStatistics getQueryStatistics(String hql) {
return stats.getQueryStatistics(hql);
}
@ManagedAttribute
public long getEntityDeleteCount() {
return stats.getEntityDeleteCount();
}
@ManagedAttribute
public long getEntityInsertCount() {
return stats.getEntityInsertCount();
}
@ManagedAttribute
public long getEntityLoadCount() {
return stats.getEntityLoadCount();
}
@ManagedAttribute
public long getEntityFetchCount() {
return stats.getEntityFetchCount();
}
@ManagedAttribute
public long getEntityUpdateCount() {
return stats.getEntityUpdateCount();
}
@ManagedAttribute
public long getQueryExecutionCount() {
return stats.getQueryExecutionCount();
}
@ManagedAttribute
public long getQueryCacheHitCount() {
return stats.getQueryCacheHitCount();
}
@ManagedAttribute
public long getQueryExecutionMaxTime() {
return stats.getQueryExecutionMaxTime();
}
@ManagedAttribute
public long getQueryCacheMissCount() {
return stats.getQueryCacheMissCount();
}
@ManagedAttribute
public long getQueryCachePutCount() {
return stats.getQueryCachePutCount();
}
@ManagedAttribute
public long getFlushCount() {
return stats.getFlushCount();
}
@ManagedAttribute
public long getConnectCount() {
return stats.getConnectCount();
}
@ManagedAttribute
public long getSecondLevelCacheHitCount() {
return stats.getSecondLevelCacheHitCount();
}
@ManagedAttribute
public long getSecondLevelCacheMissCount() {
return stats.getSecondLevelCacheMissCount();
}
@ManagedAttribute
public long getSecondLevelCachePutCount() {
return stats.getSecondLevelCachePutCount();
}
@ManagedAttribute
public long getSessionCloseCount() {
return stats.getSessionCloseCount();
}
@ManagedAttribute
public long getSessionOpenCount() {
return stats.getSessionOpenCount();
}
@ManagedAttribute
public long getCollectionLoadCount() {
return stats.getCollectionLoadCount();
}
@ManagedAttribute
public long getCollectionFetchCount() {
return stats.getCollectionFetchCount();
}
@ManagedAttribute
public long getCollectionUpdateCount() {
return stats.getCollectionUpdateCount();
}
@ManagedAttribute
public long getCollectionRemoveCount() {
return stats.getCollectionRemoveCount();
}
@ManagedAttribute
public long getCollectionRecreateCount() {
return stats.getCollectionRecreateCount();
}
@ManagedAttribute
public long getStartTime() {
return stats.getStartTime();
}
@ManagedAttribute
public boolean isStatisticsEnabled() {
return stats.isStatisticsEnabled();
}
@ManagedOperation
public void setStatisticsEnabled(boolean enable) {
stats.setStatisticsEnabled(enable);
}
@ManagedOperation
public void logSummary() {
stats.logSummary();
}
@ManagedAttribute
public String[] getCollectionRoleNames() {
return stats.getCollectionRoleNames();
}
@ManagedAttribute
public String[] getEntityNames() {
return stats.getEntityNames();
}
@ManagedAttribute
public String[] getQueries() {
return stats.getQueries();
}
@ManagedAttribute
public String[] getSecondLevelCacheRegionNames() {
return stats.getSecondLevelCacheRegionNames();
}
@ManagedAttribute
public long getSuccessfulTransactionCount() {
return stats.getSuccessfulTransactionCount();
}
@ManagedAttribute
public long getTransactionCount() {
return stats.getTransactionCount();
}
@ManagedAttribute
public long getCloseStatementCount() {
return stats.getCloseStatementCount();
}
@ManagedAttribute
public long getPrepareStatementCount() {
return stats.getPrepareStatementCount();
}
@ManagedAttribute
public long getOptimisticFailureCount() {
return stats.getOptimisticFailureCount();
}
@ManagedAttribute
public String getQueryExecutionMaxTimeQueryString() {
return stats.getQueryExecutionMaxTimeQueryString();
}
}
Upvotes: 2
Reputation: 273
I just performed a hibernate upgrade.
The best solution I found was to just copy the StatisticsService and the interface from the old hibernate jar, use the same package, etc
This means it also works with the hibernate-jconsole plugin, which is a nice plus. :)
Upvotes: 1
Reputation: 630
@Harek's answer works, but since it creates an MXBean (a stricter version of an MBean) it breaks compatibility with the Hibernate JConsole plugin (http://hibernate-jcons.sourceforge.net/).
Nevertheless it is the best solution I have seen so far, most people probably don't know about or use that plugin anyway.
Upvotes: 1
Reputation: 465
seems to be a bug after refactoring in hibernate. see https://hibernate.atlassian.net/browse/HHH-6190 for details
Here's a workaround I've used, utilising a java dynamic proxy to represent the statistics interface from hibernate, and the default platform mbean server:
@MXBean
public interface StatisticsMXBean extends Statistics {
}
public void initStatistics(SessionFactory sessionFactory) {
ObjectName statsName = new ObjectName("org.hibernate:type=statistics");
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
final Statistics statistics = sessionFactory.getStatistics();
statistics.setStatisticsEnabled(true);
Object statisticsMBean = Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { StatisticsMXBean.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(statistics, args);
}
});
mbeanServer.registerMBean(statisticsMBean, statsName);
}
Upvotes: 9