All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.ehcache.management.ManagementService Maven / Gradle / Ivy

/**
 *  Copyright Terracotta, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package net.sf.ehcache.management;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.Status;
import net.sf.ehcache.distribution.CacheManagerPeerProvider;
import net.sf.ehcache.event.CacheManagerEventListener;
import net.sf.ehcache.hibernate.management.impl.EhcacheHibernateMbeanNames;

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 java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Ehcache CacheManagers and Caches have lifecycles. Often normal use of a CacheManager
 * will be to shut it down and create a new one from within a running JVM. For example,
 * in Java EE environments, applications are often undeployed and then redeployed. A
 * servlet listener available in the web module, net.sf.ehcache.constructs.web.ShutdownListener}
 * enables this to be detected and the CacheManager shutdown.
 * 

* When a CacheManager is shut down we need to ensure there is no memory, resource or * thread leakage. An MBeanServer, particularly a platform MBeanServer, can be expected * to exist for the lifespan of the JVM. Accordingly, we need to deregister them when * needed without creating a leakage. *

* The second purpose of this class (and this package) is to keep management concerns away * from the core ehcache packages. That way, JMX is not a required dependency, but rather * an optional one. *

* This class is constructable as of 1.5 to support injection via IoC containers. * * @author Greg Luck * @version $Id: ManagementService.java 5631 2012-05-10 08:31:33Z teck $ * @since 1.3 */ public class ManagementService implements CacheManagerEventListener { private static final Logger LOG = LoggerFactory.getLogger(ManagementService.class.getName()); private MBeanServer mBeanServer; private net.sf.ehcache.CacheManager backingCacheManager; private boolean registerCacheManager; private boolean registerCaches; private boolean registerCacheConfigurations; private boolean registerCacheStatistics; private boolean registerCacheStores; private Status status; /** * A constructor for a management service for a range of possible MBeans. *

* The {@link #init()} method needs to be called after construction which causes * the selected monitoring options to be be registered * with the provided MBeanServer for caches in the given CacheManager. *

* While registering the CacheManager enables traversal to all of the other * items, * this requires programmatic traversal. The other options allow entry points closer * to an item of interest and are more accessible from JMX management tools like JConsole. * Moreover CacheManager and Cache are not serializable, so remote monitoring is not possible * for CacheManager or Cache, while CacheStatistics and CacheConfiguration are. Finally * CacheManager and Cache enable management operations to be performed. *

* Once monitoring is enabled caches will automatically added and removed from the MBeanServer * as they are added and disposed of from the CacheManager. When the CacheManager itself * shutsdown all registered MBeans will be unregistered. * * @param cacheManager the CacheManager to listen to * @param mBeanServer the MBeanServer to register MBeans to * @param registerCacheManager Whether to register the CacheManager MBean * @param registerCaches Whether to register the Cache MBeans * @param registerCacheConfigurations Whether to register the CacheConfiguration MBeans * @param registerCacheStatistics Whether to register the CacheStatistics MBeans * @throws net.sf.ehcache.CacheException if something goes wrong with init() * @since 2.2 */ public ManagementService(net.sf.ehcache.CacheManager cacheManager, MBeanServer mBeanServer, boolean registerCacheManager, boolean registerCaches, boolean registerCacheConfigurations, boolean registerCacheStatistics, boolean registerCacheStores) throws CacheException { status = Status.STATUS_UNINITIALISED; backingCacheManager = cacheManager; this.mBeanServer = mBeanServer; this.registerCacheManager = registerCacheManager; this.registerCaches = registerCaches; this.registerCacheConfigurations = registerCacheConfigurations; this.registerCacheStatistics = registerCacheStatistics; this.registerCacheStores = registerCacheStores; } /** * A constructor for a management service for a range of possible MBeans. *

* The {@link #init()} method needs to be called after construction which causes * the selected monitoring options to be be registered * with the provided MBeanServer for caches in the given CacheManager. *

* While registering the CacheManager enables traversal to all of the other * items, * this requires programmatic traversal. The other options allow entry points closer * to an item of interest and are more accessible from JMX management tools like JConsole. * Moreover CacheManager and Cache are not serializable, so remote monitoring is not possible * for CacheManager or Cache, while CacheStatistics and CacheConfiguration are. Finally * CacheManager and Cache enable management operations to be performed. *

* Once monitoring is enabled caches will automatically added and removed from the MBeanServer * as they are added and disposed of from the CacheManager. When the CacheManager itself * shutsdown all registered MBeans will be unregistered. * * @param cacheManager the CacheManager to listen to * @param mBeanServer the MBeanServer to register MBeans to * @param registerCacheManager Whether to register the CacheManager MBean * @param registerCaches Whether to register the Cache MBeans * @param registerCacheConfigurations Whether to register the CacheConfiguration MBeans * @param registerCacheStatistics Whether to register the CacheStatistics MBeans * @throws net.sf.ehcache.CacheException if something goes wrong with init() */ public ManagementService(net.sf.ehcache.CacheManager cacheManager, MBeanServer mBeanServer, boolean registerCacheManager, boolean registerCaches, boolean registerCacheConfigurations, boolean registerCacheStatistics) throws CacheException { this(cacheManager, mBeanServer, registerCacheManager, registerCaches, registerCacheConfigurations, registerCacheStatistics, false); } /** * A convenience static method which creates a ManagementService and initialises it with the * supplied parameters. * * @param cacheManager the CacheManager to listen to * @param mBeanServer the MBeanServer to register MBeans to * @param registerCacheManager Whether to register the CacheManager MBean * @param registerCaches Whether to register the Cache MBeans * @param registerCacheConfigurations Whether to register the CacheConfiguration MBeans * @param registerCacheStatistics Whether to register the CacheStatistics MBeans * @see ManagementService#ManagementService(net.sf.ehcache.CacheManager, javax.management.MBeanServer, boolean, boolean, boolean, boolean, boolean) * @since 2.2 */ public static void registerMBeans( net.sf.ehcache.CacheManager cacheManager, MBeanServer mBeanServer, boolean registerCacheManager, boolean registerCaches, boolean registerCacheConfigurations, boolean registerCacheStatistics, boolean registerCacheStores) throws CacheException { ManagementService registry = new ManagementService(cacheManager, mBeanServer, registerCacheManager, registerCaches, registerCacheConfigurations, registerCacheStatistics, registerCacheStores); registry.init(); } /** * A convenience static method which creates a ManagementService and initialises it with the * supplied parameters. *

* This one is provided for backward compatibility * * @param cacheManager the CacheManager to listen to * @param mBeanServer the MBeanServer to register MBeans to * @param registerCacheManager Whether to register the CacheManager MBean * @param registerCaches Whether to register the Cache MBeans * @param registerCacheConfigurations Whether to register the CacheConfiguration MBeans * @param registerCacheStatistics Whether to register the CacheStatistics MBeans * @see ManagementService#ManagementService(net.sf.ehcache.CacheManager, javax.management.MBeanServer, boolean, boolean, boolean, boolean) */ public static void registerMBeans( net.sf.ehcache.CacheManager cacheManager, MBeanServer mBeanServer, boolean registerCacheManager, boolean registerCaches, boolean registerCacheConfigurations, boolean registerCacheStatistics) throws CacheException { registerMBeans(cacheManager, mBeanServer, registerCacheManager, registerCaches, registerCacheConfigurations, registerCacheStatistics, false); } /** * Call to register the mbeans in the mbean server and start the event listeners and do any other required initialisation. * Once intialised, it registers itself as a CacheManageEvenListener with the backing CacheManager, so * that it can participate in lifecycle and other events. * * @throws net.sf.ehcache.CacheException - all exceptions are wrapped in CacheException */ public void init() throws CacheException { CacheManager cacheManager = new CacheManager(backingCacheManager); try { registerCacheManager(cacheManager); registerPeerProviders(); List caches = cacheManager.getCaches(); for (int i = 0; i < caches.size(); i++) { Cache cache = (Cache) caches.get(i); registerCachesIfRequired(cache); registerCacheStatisticsIfRequired(cache); registerCacheConfigurationIfRequired(cache); registerCacheStoreIfRequired(cache); } } catch (Exception e) { throw new CacheException(e); } status = Status.STATUS_ALIVE; backingCacheManager.getCacheManagerEventListenerRegistry().registerListener(this); } private void registerPeerProviders() { final Map cacheManagerPeerProviders = this.backingCacheManager.getCacheManagerPeerProviders(); for (final CacheManagerPeerProvider cacheManagerPeerProvider : cacheManagerPeerProviders.values()) { if (cacheManagerPeerProvider instanceof ManagedCacheManagerPeerProvider) { ((ManagedCacheManagerPeerProvider) cacheManagerPeerProvider).register(this.mBeanServer); } } } private void registerCacheManager(CacheManager cacheManager) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (registerCacheManager) { mBeanServer.registerMBean(cacheManager, cacheManager.getObjectName()); } } private void registerCacheConfigurationIfRequired(Cache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (registerCacheConfigurations) { CacheConfiguration cacheConfiguration = cache.getCacheConfiguration(); mBeanServer.registerMBean(cacheConfiguration, cacheConfiguration.getObjectName()); } } private void registerCacheStatisticsIfRequired(Cache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (registerCacheStatistics) { CacheStatistics cacheStatistics = cache.getStatistics(); mBeanServer.registerMBean(cacheStatistics, cacheStatistics.getObjectName()); } } private void registerCachesIfRequired(Cache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (registerCaches) { mBeanServer.registerMBean(cache, cache.getObjectName()); } } private void registerCacheStoreIfRequired(Cache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (registerCacheStores) { Store cacheStore = cache.getStore(); if (cacheStore != null) { mBeanServer.registerMBean(cacheStore, cacheStore.getObjectName()); } } } /** * Returns the listener status. * * @return the status at the point in time the method is called */ public Status getStatus() { return status; } /** * Stop the listener and free any resources. * Removes registered ObjectNames * * @throws net.sf.ehcache.CacheException - all exceptions are wrapped in CacheException */ public void dispose() throws CacheException { Set registeredObjectNames = null; try { // CacheManager MBean registeredObjectNames = mBeanServer.queryNames(CacheManager.createObjectName(backingCacheManager), null); // Other MBeans for this CacheManager registeredObjectNames.addAll(mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*,CacheManager=" + EhcacheHibernateMbeanNames.mbeanSafe(backingCacheManager.toString())), null)); } catch (MalformedObjectNameException e) { // this should not happen LOG.error("Error querying MBeanServer. Error was " + e.getMessage(), e); } for (Iterator iterator = registeredObjectNames.iterator(); iterator.hasNext();) { ObjectName objectName = (ObjectName) iterator.next(); try { mBeanServer.unregisterMBean(objectName); } catch (Exception e) { LOG.error("Error unregistering object instance " + objectName + " . Error was " + e.getMessage(), e); } } status = Status.STATUS_SHUTDOWN; } /** * Called immediately after a cache has been added and activated. *

* Note that the CacheManager calls this method from a synchronized method. Any attempt to * call a synchronized method on CacheManager from this method will cause a deadlock. *

* Note that activation will also cause a CacheEventListener status change notification * from {@link net.sf.ehcache.Status#STATUS_UNINITIALISED} to * {@link net.sf.ehcache.Status#STATUS_ALIVE}. Care should be taken on processing that * notification because: *

    *
  • the cache will not yet be accessible from the CacheManager. *
  • the addCaches methods which cause this notification are synchronized on the * CacheManager. An attempt to call {@link net.sf.ehcache.CacheManager#getEhcache(String)} * will cause a deadlock. *
* The calling method will block until this method returns. *

* * @param cacheName the name of the Cache the operation relates to * @see net.sf.ehcache.event.CacheEventListener */ public void notifyCacheAdded(String cacheName) { if (registerCaches || registerCacheStatistics || registerCacheConfigurations) { Cache cache = new Cache(backingCacheManager.getEhcache(cacheName)); try { registerCachesIfRequired(cache); registerCacheStatisticsIfRequired(cache); registerCacheConfigurationIfRequired(cache); registerCacheStoreIfRequired(cache); } catch (Exception e) { LOG.error("Error registering cache for management for " + cache.getObjectName() + " . Error was " + e.getMessage(), e); } } } /** * Called immediately after a cache has been disposed and removed. The calling method will * block until this method returns. *

* Note that the CacheManager calls this method from a synchronized method. Any attempt to * call a synchronized method on CacheManager from this method will cause a deadlock. *

* Note that a {@link net.sf.ehcache.event.CacheEventListener} status changed will also be triggered. Any * attempt from that notification to access CacheManager will also result in a deadlock. * * @param cacheName the name of the Cache the operation relates to */ public void notifyCacheRemoved(String cacheName) { ObjectName objectName = null; try { if (registerCaches) { objectName = Cache.createObjectName(backingCacheManager.toString(), cacheName); mBeanServer.unregisterMBean(objectName); } if (registerCacheConfigurations) { objectName = CacheConfiguration.createObjectName(backingCacheManager.toString(), cacheName); mBeanServer.unregisterMBean(objectName); } if (registerCacheStatistics) { objectName = CacheStatistics.createObjectName(backingCacheManager.toString(), cacheName); mBeanServer.unregisterMBean(objectName); } if (registerCacheStores) { objectName = Store.createObjectName(backingCacheManager.toString(), cacheName); if (mBeanServer.isRegistered(objectName)) { mBeanServer.unregisterMBean(objectName); } } } catch (Exception e) { LOG.error("Error unregistering cache for management for " + objectName + " . Error was " + e.getMessage(), e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy