org.hyperic.hibernate.CacheInitializingLocalSessionFactoryBean.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hibernate.CacheInitializingLocalSessionFactoryBean.java

Source

/**
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 *  "derived work".
 *
 *  Copyright (C) [2010], VMware, Inc.
 *  This file is part of HQ.
 *
 *  HQ is free software; you can redistribute it and/or modify
 *  it under the terms version 2 of the GNU General Public License as
 *  published by the Free Software Foundation. This program is distributed
 *  in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 *  PARTICULAR PURPOSE. See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *  USA.
 *
 */

package org.hyperic.hibernate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.management.ManagementService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.jmx.StatisticsService;
import org.hyperic.hq.common.DiagnosticObject;
import org.hyperic.hq.common.DiagnosticsLogger;
import org.hyperic.util.PrintfFormat;
import org.hyperic.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

/**
 * Extension of the {@link LocalSessionFactoryBean} that preloads the 2nd level
 * cache for performance optimizations and registers Hibernate and EhCache stat
 * MBeans
 * @author jhickey
 * 
 */
public class CacheInitializingLocalSessionFactoryBean extends LocalSessionFactoryBean {

    private final List<String> classesForCache;

    private final Log log = LogFactory.getLog(CacheInitializingLocalSessionFactoryBean.class);

    @Autowired
    private MBeanServer mBeanServer;

    @Autowired
    private DiagnosticsLogger diagnosticsLogger;

    //required for proper shutdown 
    private DiagnosticObject cacheDiagnostics;

    private static final String HIBERNATE_STATS_OBJECT_NAME = "Hibernate:type=statistics,application=hq";

    public CacheInitializingLocalSessionFactoryBean(List<String> classesForCache) {
        super();
        this.classesForCache = classesForCache;
    }

    @Override
    public void destroy() throws HibernateException {
        super.destroy();
        try {
            mBeanServer.unregisterMBean(new ObjectName(HIBERNATE_STATS_OBJECT_NAME));
        } catch (Exception e) {
            logger.warn("Error unregistering Hibernate Stats MBean", e);
        }

        //remove the cache diagnostic object from the logger 
        this.diagnosticsLogger.removeDiagnosticObject(this.cacheDiagnostics);
    }

    @Override
    protected void afterSessionFactoryCreation() throws Exception {
        super.afterSessionFactoryCreation();
        final Configuration configurations = this.getConfiguration();
        if (configurations != null) {
            log.info("DATABASE CONNECTION URL: " + this.getConfiguration().getProperty("hibernate.connection.url"));
        } //EO if configuration were provided 
        registerMBeans();
        initEhCacheDiagnostics();
        preloadCache();
    }

    private void registerMBeans() throws MalformedObjectNameException, InstanceAlreadyExistsException,
            MBeanRegistrationException, NotCompliantMBeanException {
        ObjectName on = new ObjectName(HIBERNATE_STATS_OBJECT_NAME);
        StatisticsService mBean = new StatisticsService();
        mBean.setSessionFactory(getSessionFactory());
        mBeanServer.registerMBean(mBean, on);
        ManagementService.registerMBeans(CacheManager.getInstance(), mBeanServer, false, false, false, true);
    }

    @SuppressWarnings("unchecked")
    private void preloadCache() {
        Session session = SessionFactoryUtils.getSession(getSessionFactory(), true);
        for (String className : classesForCache) {
            Class<?> clazz;
            className = className.trim();
            if (className.length() == 0 || className.startsWith("#")) {
                continue;
            }
            try {
                clazz = Class.forName(className);
            } catch (Exception e) {
                log.warn("Unable to find preload cache for class [" + className + "]", e);
                continue;
            }
            long start = System.currentTimeMillis();
            Collection<Object> vals = session.createCriteria(clazz).list();
            long end = System.currentTimeMillis();
            log.info("Preloaded " + vals.size() + " [" + clazz.getName() + "] in " + (end - start) + " millis");
            // Evict, to avoid dirty checking everything in the inventory
            for (Object val : vals) {
                session.evict(val);
            }
        }
    }

    private void initEhCacheDiagnostics() {
        // Add ehcache statistics to the diagnostics
        this.cacheDiagnostics = new DiagnosticObject() {
            private final PrintfFormat _fmt = new PrintfFormat("%-55s %-6d %-6d %6d");
            private final PrintfFormat _hdr = new PrintfFormat("%-55s %-6s %-6s %6s");

            public String getName() {
                return "EhCache Diagnostics";
            }

            public String getShortName() {
                return "ehcacheDiag";
            }

            private List<Cache> getSortedCaches() {
                List<Cache> res = getCaches();

                Collections.sort(res, new Comparator<Cache>() {
                    public int compare(Cache c1, Cache c2) {
                        return c1.getName().compareTo(c2.getName());
                    }
                });
                return res;
            }

            public String getStatus() {
                String separator = System.getProperty("line.separator");
                StringBuffer buf = new StringBuffer(separator);
                Object[] fmtArgs = new Object[5];

                fmtArgs[0] = "Cache";
                fmtArgs[1] = "Size";
                fmtArgs[2] = "Hits";
                fmtArgs[3] = "Misses";
                buf.append(_hdr.sprintf(fmtArgs)).append(separator);
                fmtArgs[0] = "=====";
                fmtArgs[1] = "====";
                fmtArgs[2] = "====";
                fmtArgs[3] = "=====";
                buf.append(_hdr.sprintf(fmtArgs));

                for (Cache cache : getSortedCaches()) {
                    fmtArgs[0] = StringUtil.dotProximate(cache.getName(), 55);
                    fmtArgs[1] = new Integer(cache.getSize());
                    fmtArgs[2] = new Long(cache.getStatistics().getCacheHits());
                    fmtArgs[3] = new Long(cache.getStatistics().getCacheMisses());

                    buf.append(separator).append(_fmt.sprintf(fmtArgs));
                }

                return buf.toString();
            }

            public String getShortStatus() {
                return getStatus();
            }

            @Override
            public String toString() {
                return "ehcache";
            }
        };
        diagnosticsLogger.addDiagnosticObject(cacheDiagnostics);
    }

    private List<Cache> getCaches() {
        CacheManager cacheManager = CacheManager.getInstance();
        String[] caches = cacheManager.getCacheNames();
        List<Cache> res = new ArrayList<Cache>(caches.length);

        for (int i = 0; i < caches.length; i++) {
            res.add(cacheManager.getCache(caches[i]));
        }
        return res;
    }
}