Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== RCS file: /usr/local/cvsroot/lams_admin/conf/language/lams/ApplicationResources.properties,v diff -u -r1.77 -r1.78 --- lams_admin/conf/language/lams/ApplicationResources.properties 13 Feb 2012 02:37:07 -0000 1.77 +++ lams_admin/conf/language/lams/ApplicationResources.properties 22 Feb 2012 13:26:13 -0000 1.78 @@ -172,10 +172,15 @@ cache.maintain =Maintain LAMS Cache cache.title =Cache Management cache.entries.title =Cache Nodes +cache.entries.title2 =Cacheable entities cache.explanation1 =Listed below are the current nodes in the cache. This keeps certain common objects in memory to speed up LAMS. It is managed automatically and should not require any intervention. However, if the system appears to be keeping "old values" e.g. an old first name, try clearing all the nodes in the cache. Once cleared, LAMS will reload the objects from the database. cache.explanation2 =Warning: Removing nodes will reduce the performance of the LAMS server. After a while, the cache will build up again and LAMS will run as usual. cache.explanation3 =Warning: If you remove a node, you will remove the node and all its child nodes. +cache.explanation4 =Listed below are cacheable classes and collections. This keeps certain common objects in memory to speed up LAMS. It is managed automatically and should not require any intervention. However, if the system appears to be keeping "old values" e.g. an old first name, try clearing all the nodes in the cache. Once cleared, LAMS will reload the objects from the database. cache.button.remove =Remove +cache.button.remove.all =Clear all cached objects +cache.removed =Objects bound with entity name {0} were removed +cache.removed.all =All cached objects were removed admin.config.key =Key admin.config.value =Value admin.register.sitename =Full Sitename Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/CacheAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_admin/src/java/org/lamsfoundation/lams/admin/web/CacheAction.java,v diff -u -r1.6 -r1.7 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/CacheAction.java 17 Sep 2006 06:10:13 -0000 1.6 +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/CacheAction.java 22 Feb 2012 13:26:14 -0000 1.7 @@ -25,6 +25,7 @@ import java.io.IOException; import java.util.Map; +import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -35,15 +36,16 @@ import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.lamsfoundation.lams.cache.CacheManager; +import org.lamsfoundation.lams.cache.ICacheManager; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.action.LamsDispatchAction; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** - * this is an action where all lams client environments launch. - * initial configuration of the individual environment setting is done here. + * This is an action where all lams client environments launch. + * Initial configuration of the individual environment setting is done here. * * @struts:action name="CacheActionForm" * path="/cache" @@ -58,7 +60,7 @@ public static final String NODE_KEY = "node"; private static Logger log = Logger.getLogger(CacheAction.class); - private static CacheManager manager; + private static ICacheManager cacheManager; /** * request for sysadmin environment */ @@ -67,11 +69,12 @@ throws IOException, ServletException { try { + if (log.isDebugEnabled()) { + log.debug("Cache lookup"); + } - log.debug("cache lookup"); - // todo restrict access to admin only. Can't do at present as don't know orgID - log.error("CacheAction should be restricted to admin only. No check being done. Please implement."); + log.warn("CacheAction should be restricted to admin only. No check being done. Please implement."); /*String login = req.getRemoteUser(); int orgId = new Integer(req.getParameter("orgId")).intValue(); @@ -88,7 +91,7 @@ return mapping.findForward("error"); } */ - Map items = getManager().getCachedItems(); + Set items = getCacheManager().getCachedClasses(); req.setAttribute(CACHE_ENTRIES, items); return mapping.findForward("cache"); @@ -106,46 +109,34 @@ throws IOException, ServletException { try { - - log.debug("remove"); - - // todo restrict access to admin only. Can't do at present as don't know orgID - log.error("CacheAction should be restricted to admin only. No check being done. Please implement."); - /*String login = req.getRemoteUser(); - int orgId = new Integer(req.getParameter("orgId")).intValue(); - - if ( isUserInRole(login,orgId,Role.ADMIN)) - { - log.debug("user is admin"); - Organisation org = service.getOrganisationById(new Integer(orgId)); - AdminPreparer.prepare(org,req,service); - return mapping.findForward("admin"); + // todo restrict access to admin only. Can't do at present as don't know orgID + + if (log.isDebugEnabled()) { + log.debug("Remove entity from cache"); } - else - { - log.error("User "+login+" tried to get cache admin screen but isn't admin in organisation: "+orgId); - return mapping.findForward("error"); - } */ + String node = WebUtil.readStrParam(req, NODE_KEY); - String node = WebUtil.readStrParam(req, NODE_KEY, false); - getManager().clearCache(node); + // if node = ALL, remove all cache + getCacheManager().clearCachedClass(node.equalsIgnoreCase("ALL") ? null : node); - Map items = getManager().getCachedItems(); - req.setAttribute(CACHE_ENTRIES, items); - return mapping.findForward("cache"); + // so we know what entity has been removed + req.setAttribute(NODE_KEY, node); + // display the list again + return unspecified(mapping,form,req,res); + } catch (Exception e) { e.printStackTrace(); return mapping.findForward("error"); } } - private CacheManager getManager(){ - if(manager==null){ + private ICacheManager getCacheManager(){ + if(cacheManager==null){ WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet().getServletContext()); - manager = (CacheManager) ctx.getBean("cacheManager"); + cacheManager = (CacheManager) ctx.getBean("cacheManager"); } - return manager; + return cacheManager; } } \ No newline at end of file Index: lams_admin/web/cache.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_admin/web/cache.jsp,v diff -u -r1.10 -r1.11 --- lams_admin/web/cache.jsp 14 Dec 2007 04:18:18 -0000 1.10 +++ lams_admin/web/cache.jsp 22 Feb 2012 13:26:13 -0000 1.11 @@ -5,23 +5,36 @@


-

+

-

- - + +
+ + + + + + + ${node} + + + +
+
-

+ -

Index: lams_build/build.xml =================================================================== RCS file: /usr/local/cvsroot/lams_build/build.xml,v diff -u -r1.95 -r1.96 --- lams_build/build.xml 7 Feb 2012 16:50:34 -0000 1.95 +++ lams_build/build.xml 22 Feb 2012 13:26:21 -0000 1.96 @@ -489,9 +489,6 @@ - Fisheye: Tag 1.3 refers to a dead (removed) revision in file `lams_build/conf/unix/jboss/service/lams-cache-jboss-beans.xml'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.3 refers to a dead (removed) revision in file `lams_build/conf/windows/jboss/service/lams-cache-jboss-beans.xml'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/applicationContext.xml =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/applicationContext.xml,v diff -u -r1.8 -r1.9 --- lams_common/src/java/org/lamsfoundation/lams/applicationContext.xml 1 Jul 2009 02:47:11 -0000 1.8 +++ lams_common/src/java/org/lamsfoundation/lams/applicationContext.xml 22 Feb 2012 13:26:17 -0000 1.9 @@ -26,8 +26,8 @@ jboss.cache:service=TreeCache + Index: lams_common/src/java/org/lamsfoundation/lams/cache/CacheManager.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/cache/CacheManager.java,v diff -u -r1.9 -r1.10 --- lams_common/src/java/org/lamsfoundation/lams/cache/CacheManager.java 1 Jul 2009 02:47:10 -0000 1.9 +++ lams_common/src/java/org/lamsfoundation/lams/cache/CacheManager.java 22 Feb 2012 13:26:17 -0000 1.10 @@ -25,14 +25,21 @@ import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import javax.management.MBeanServer; import javax.management.MBeanServerInvocationHandler; import javax.management.ObjectName; +import org.apache.commons.lang.NotImplementedException; import org.apache.log4j.Logger; +import org.hibernate.SessionFactory; +import org.hibernate.metadata.ClassMetadata; +import org.hibernate.persister.collection.AbstractCollectionPersister; +import org.hibernate.persister.entity.EntityPersister; import org.jboss.cache.Cache; import org.jboss.cache.CacheException; import org.jboss.cache.Fqn; @@ -51,6 +58,7 @@ /* Spring configured variables */ private String cacheObjectName = null; + private SessionFactory sessionFactory; /* * There is one cache across the whole system, so it should be safe to use a static cache bean. Do not use this @@ -66,6 +74,11 @@ * required. */ private Cache getCache() { + throw new NotImplementedException("You can not retrieve Cache using JMX on current JBoss version"); + + /* OLD implementation, to be revised on next JBoss upgrade + + if (cache == null) { try { @@ -76,7 +89,8 @@ * When migrating to JBoss 5, the way the Cache is accessed had to be changed. Also, currently Cache is * not exposed by JMX, so it is also unavailable for Cache Manager. Trying to retrieve it causes an * error. This will be fixed in the future. - */ + * / + MBeanServer server = JMXUtil.getMBeanServer(); CacheJmxWrapperMBean wrapper = (CacheJmxWrapperMBean) MBeanServerInvocationHandler.newProxyInstance( server, ObjectName.getInstance(cacheObjectName), CacheJmxWrapperMBean.class, false); @@ -98,6 +112,7 @@ } } return cache; + */ } /** Get the String[] version of the objects class name. */ @@ -206,7 +221,7 @@ } } - public Map getCachedItems() { + public Map> getCachedItems() { Cache cache = getCache(); Map allChildNames = new TreeMap(); if (cache == null) { @@ -217,6 +232,48 @@ return allChildNames; } + public Set getCachedClasses() { + Set cachedClasses = new TreeSet(); + + for (Entry cacheEntry : ((Map) getSessionFactory() + .getAllClassMetadata()).entrySet()) { + if (cacheEntry.getValue().hasCache()) { + cachedClasses.add(cacheEntry.getKey()); + } + } + + for (Entry cacheEntry : ((Map) getSessionFactory() + .getAllCollectionMetadata()).entrySet()) { + if (cacheEntry.getValue().hasCache()) { + cachedClasses.add(cacheEntry.getKey()); + } + } + + return cachedClasses; + } + + public void clearCachedClass(String className) { + for (Entry cacheEntry : ((Map) getSessionFactory() + .getAllClassMetadata()).entrySet()) { + if ((className == null || className.equals(cacheEntry.getKey())) && cacheEntry.getValue().hasCache()) { + getSessionFactory().evictEntity(cacheEntry.getKey()); + if (log.isDebugEnabled()) { + log.debug("Evicted entity: " + cacheEntry.getKey()); + } + } + } + + for (Entry cacheEntry : ((Map) getSessionFactory() + .getAllCollectionMetadata()).entrySet()) { + if ((className == null || className.equals(cacheEntry.getKey())) && cacheEntry.getValue().hasCache()) { + getSessionFactory().evictCollection(cacheEntry.getKey()); + if (log.isDebugEnabled()) { + log.debug("Evicted collection: " + cacheEntry.getKey()); + } + } + } + } + /* * Recursively add all the child nodes to the map. This is where the format of FQNs is important - this code will * hardcode in "/" between each step. @@ -283,4 +340,11 @@ this.cacheObjectName = cacheObjectName; } -} + public SessionFactory getSessionFactory() { + return sessionFactory; + } + + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/cache/ICacheManager.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/cache/ICacheManager.java,v diff -u -r1.7 -r1.8 --- lams_common/src/java/org/lamsfoundation/lams/cache/ICacheManager.java 17 Sep 2006 06:14:20 -0000 1.7 +++ lams_common/src/java/org/lamsfoundation/lams/cache/ICacheManager.java 22 Feb 2012 13:26:17 -0000 1.8 @@ -24,6 +24,9 @@ package org.lamsfoundation.lams.cache; +import java.util.Map; +import java.util.Set; + /** Wraps up the JBOSS Cache in some simple methods to add, get and * remove an object to/from the cache. Used for manually caching objects, * rather than Hibernate managed objects. @@ -43,6 +46,14 @@ * If errors occur putting values in the cache, or getting values from the cache, * then they will be logged in the server log. Exceptions are not thrown - better * to have the system degrade if the cache isn't available, rather than failing. + * + * JBOSS 5 UPDATE: + * Due to difficulties in accessing Cache through JMX after upgrade to JBoss 5, + * described in LDEV-2071 and LDEV-2811, methods manipulating Cache directly + * are now foribidden and throw an exception. + * These methods are not used anywhere in LAMS now, but might become handy in future development + * and should be reimplemented once necessary tools become available on newer JBoss distribution. + * Only new methods based on cached Entity manipulation, not Nodes, are currently available. */ public interface ICacheManager { @@ -82,6 +93,20 @@ /** * Remove a particular item from the cache. */ - public abstract void removeItem(String[] classNameParts, Object key); - -} \ No newline at end of file + public abstract void removeItem(String[] classNameParts, Object key); + + /** + * Gets hierarchical structure of Node -> Children. + */ + public abstract Map> getCachedItems(); + + /** + * Gets flat set of cached Classes and Collection roles. + */ + public abstract Set getCachedClasses(); + + /** + * Evicts all entities given by Class name or Collection role. + */ + public abstract void clearCachedClass(String className); + } \ No newline at end of file