在jboss 4.2.1中启用ehcache统计信息

时间:2008-10-30 20:52:47

标签: hibernate jboss java-ee persistence ehcache

我已经设置了hibernate.generate_statistics = true,现在需要注册mbeans,以便我可以在jmx控制台中看到统计信息。我似乎无法到达任何地方,这似乎不应该是一个如此困难的问题。也许我让事情变得过于复杂,但无论如何到目前为止我都尝试过:

  • 我复制了EhCacheProvider并让它实例化了一个扩展版本的CacheManager,它在初始化后重载了init()并调用了ManagementService.registerMBeans(...)。代码都运行良好,直到实际调用registerMBeans(...),这会导致提供程序初始化失败并出现一般错误(遗憾的是我没有将其写下来。)这种方法是由{{}中使用的方法推动的。 3}}
  • 我使用一个与this liferay performance walkthrough.运行类似代码的start方法创建了自己的MBean。一切似乎都正常工作,我的mbean显示在jmx控制台中,但net.sf.ehcache没有。
  • 我已经将ehcache升级到1.5(我们使用1.3,不确定是否特定于jboss 4.2.1或我们自己选择的东西)并改为使用SingletonEhCacheProvider并尝试手动获取统计信息而不是处理mbean注册。它虽然没有变得更好;如果我调用getInstance(),返回的CacheManager只有一个StandardQueryCache副本,但是jboss日志显示已经初始化了许多其他缓存(我们的应用程序中每个缓存实体都有一个)。
编辑:嗯,我已经找到了一件事......通过JConsole连接确实揭示了mbeans的统计数据。我猜ManagementFactory.getPlatformMBeanServer()不会给你提供与jboss使用相同的mbean服务器。无论如何,看起来我遇到了类似的问题,就像我手动收集统计数据时一样,因为即使点击我的应用程序后我也会得到全部零。

2 个答案:

答案 0 :(得分:1)

上面给出的答案假设正在使用SingletonEhcacheProvider并且它还需要utilmgr bean,这个其他解决方案使用启动bean并且不进行单例假设

@Name("hibernateStatistics")
@Scope(ScopeType.APPLICATION)
@Startup
public class HibernateUtils {
@In
private EntityManager entityManager;

@Create
public void onStartup() {
    if (entityManager != null) {
        try {
            //lookup the jboss mbean server
            MBeanServer beanServer = org.jboss.mx.util.MBeanServerLocator.locateJBoss();
            StatisticsService mBean = new StatisticsService();
            ObjectName objectName = new ObjectName("Hibernate:type=statistics,application=<application-name>");
            try{
                beanServer.unregisterMBean(objectName);
            }catch(Exception exc) {
                //no problems, as unregister is not important
            }
            SessionFactory sessionFactory = ((HibernateSessionProxy) entityManager.getDelegate()).getSessionFactory();
            mBean.setSessionFactory(sessionFactory);
            beanServer.registerMBean(mBean, objectName);

            if (sessionFactory instanceof SessionFactoryImplementor ){
                CacheProvider cacheProvider = ((SessionFactoryImplementor)sessionFactory).getSettings().getCacheProvider();
                if (cacheProvider instanceof EhCacheProvider)  {
                    try{
                        Field field = EhCacheProvider.class.getDeclaredField("manager");
                        field.setAccessible(true);
                        CacheManager cacheMgr = (CacheManager) field.get(cacheProvider);
                        ManagementService.registerMBeans(cacheMgr, beanServer, true, true, true, true);
                    }catch(Exception exc) {
                        //do nothing
                        exc.printStackTrace();
                    }
                }
            }

        } catch (Exception e) {
            throw new RuntimeException("The persistence context " + entityManager.toString() + "is not properly      configured.", e);
        }
    }
 }

}

我们使用MbeanServerLocator作为jboss mbean将是linux等环境中的第二个mbean服务器。

答案 1 :(得分:0)

解决。由于我没有看到我的实体的所有缓存,我怀疑我没有得到正确的SessionFactory实例。我从这一行开始(请参阅我在问题中提供的链接中的示例jmx注册码):

SessionFactory sf = (new Configuration()).configure().buildSessionFactory();

最终结果是我最终得到的缓存管理器是一个新实例而不是持久化上下文中的实例。所以我尝试重构为:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
return ((EntityManagerFactoryImpl)emf).getSessionFactory();

但是只是抛出一个异常(我不记得确切的文本;“无法初始化持久化上下文”的效果。)所以没有其他选项,我添加了一个无状态bean(UtilMgr)我的应用程序,让持久性注入正确的SessionFactory。这是豆子:

import javax.ejb.Stateless;
import javax.persistence.PersistenceUnit;
import net.sf.ehcache.CacheManager;
import org.hibernate.SessionFactory;

@Stateless
public class UtilMgrBean implements UtilMgr {
    // NOTE: rename as necessary
    @PersistenceUnit(unitName = "myPersistenceCtx")
    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    public CacheManager getCacheManager() {
        return CacheManager.getInstance(); // NOTE: assumes SingletonEhCacheProvider
    }
}

以下是前面提到的演练中的更正代码:

try {
    // NOTE: lookupBean is a utility method in our app we use for jndi lookups.
    //   replace as necessary for your application.
    UtilMgr utilMgr = (UtilMgr)Manager.lookupBean("UtilMgrBean", UtilMgr.class);
    SessionFactory sf = utilMgr.getSessionFactory();
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    // NOTE: replace myAppName as necessary
    ObjectName on = new ObjectName("Hibernate:type=statistics,application=myAppName");

    // Enable Hibernate JMX Statistics
    StatisticsService statsMBean = new StatisticsService();
    statsMBean.setSessionFactory(sf);
    statsMBean.setStatisticsEnabled(true);
    mbs.registerMBean(statsMBean, on);

    CacheManager cacheMgr = utilMgr.getCacheManager();
    ManagementService.registerMBeans(cacheMgr, mbs, true, true, true, true);
} catch(Throwable t) {
    throw new RuntimeException(t);
}

如果你想手动检索统计信息(也就是我可能会做的事情),你也可以使用UtilMgr的这个getCacheManager()方法。你可以找到更多关于如何使用Cache和Statistics对象的信息{{3 }}

如果有人可以通过静态查找会话工厂的方式填写我,而无需创建这个额外的会话bean,我很乐意听到它。