[jboss-svn-commits] JBL Code SVN: r14574 - in labs/shotoku/trunk/shotoku-cache: cache-admin/src/java/org/jboss/shotoku/cache/admin and 10 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Aug 26 05:08:09 EDT 2007


Author: adamw
Date: 2007-08-26 05:08:09 -0400 (Sun, 26 Aug 2007)
New Revision: 14574

Added:
   labs/shotoku/trunk/shotoku-cache/TODO
   labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/MonitorBean.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemOperations.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlert.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertFactory.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertImpl.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/DummyRenewableCacheMonitorService.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorServiceMBean.java
   labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/monitor/
   labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorService.java
Removed:
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemData.java
Modified:
   labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/AdminBean.java
   labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/CacheItemBean.java
   labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/WEB-INF/faces-config.xml
   labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/pages/admin.jsp
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItem.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/SignalExitUpdateThreadData.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThread.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThreadData.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/DummyRenewableCacheService.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/RenewableCacheServiceMBean.java
   labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/tools/CacheTools.java
   labs/shotoku/trunk/shotoku-cache/cache-service/src/etc/META-INF/jboss-service.xml
   labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/RenewableCacheService.java
   labs/shotoku/trunk/shotoku-cache/cache-test/src/java/org/jboss/shotoku/cache/test/TestServlet.java
Log:
Admin and monitoring

Added: labs/shotoku/trunk/shotoku-cache/TODO
===================================================================
--- labs/shotoku/trunk/shotoku-cache/TODO	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/TODO	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,8 @@
+* toggle panel
+* investigate multiple ProjectConfigurationWatcher-s
+* refreshing of keys after a key reset
+* refreshing cachitem_info after alerts reset
+* e-mail notifications of alerts
+* check form-sending for cache item configuration
+* migrate AdministratedServices
+* service unavailability when stopped; null get() when CI unregistered

Modified: labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/AdminBean.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/AdminBean.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/AdminBean.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -8,10 +8,9 @@
 
 import javax.faces.component.UIData;
 import javax.faces.context.FacesContext;
-import javax.management.MalformedObjectNameException;
 import javax.servlet.http.HttpServletRequest;
 
-import org.jboss.shotoku.cache.RenewableCacheItemData;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
 import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
 import org.jboss.shotoku.cache.service.RenewableCacheStatistics;
 import org.jboss.shotoku.tools.CacheTools;
@@ -20,11 +19,12 @@
 	private String mbeanName;
 
 	private RenewableCacheServiceMBean service;
+	
 	private List<CacheItemBean> cacheItems;
 	private long newServiceInterval;
 	private int newUpdateThreadCount;
 	
-	private List<String> currentAlerts;
+	private MonitorBean monitorBean;
 	
 	public AdminBean() {
 		// For development only.
@@ -39,8 +39,8 @@
 			}
 			
 			try {
-				service = CacheTools.getService(mbean);
-			} catch (MalformedObjectNameException e) {
+				service = (RenewableCacheServiceMBean) CacheTools.getService(mbean, RenewableCacheServiceMBean.class);
+			} catch (Exception e) {
 				throw new RuntimeException(e);
 			}
 		}
@@ -48,7 +48,6 @@
 		return service;
 	}
 	
-	
 	private final static Comparator<CacheItemBean> cacheItemBeanComparator = new Comparator<CacheItemBean>() {
 		public int compare(CacheItemBean arg0, CacheItemBean arg1) {
 			int id1 = arg0.getId();
@@ -67,18 +66,21 @@
 		
 	};
 	
+	public MonitorBean getMonitorBean() {
+		return monitorBean;
+	}
+
+	public void setMonitorBean(MonitorBean monitorBean) {
+		this.monitorBean = monitorBean;
+	}
+
 	public List<CacheItemBean> getCacheItems() {
 		if (cacheItems == null) {
-			currentAlerts = new ArrayList<String>();
 			cacheItems = new ArrayList<CacheItemBean>();
 			
-			for (RenewableCacheItemData<?> cacheItemData : getService().getCacheItemsData()) {
+			for (RenewableCacheItemOperations<?> cacheItemData : getService().getCacheItemsOperations()) {
 				CacheItemBean cacheItemBean = new CacheItemBean(cacheItemData, getService(), this);
 				cacheItems.add(cacheItemBean);
-				
-				if (cacheItemBean.isAlerted()) {
-					currentAlerts.add(cacheItemBean.getName());
-				}
 			}
 			
 			Collections.sort(cacheItems, cacheItemBeanComparator);
@@ -94,7 +96,7 @@
 	public void setMbeanName(String mbeanName) {
 		this.mbeanName = mbeanName;
 	}
-	
+
 	public long getServiceLastUpdateSecondsAgo() {
     	return (System.currentTimeMillis() - getService().getLastUpdate())/1000;
     }
@@ -139,24 +141,12 @@
     	getService().setInterval(newServiceInterval);
     	getService().setUpdateThreadCount(newUpdateThreadCount);
     	
-    	Date date = new Date();
-    	date.toString();
-    	
     	CacheFacesTools.addTimedFacesMessage("Service interval and update " +
     			"thread count changed successfully.");
     	
     	return null;
     }
     
-    public List<String> getCurrentAlerts() {
-    	getCacheItems();
-    	return currentAlerts;
-    }
-    
-    public int getCurrentAlertsSize() {
-    	return getCurrentAlerts().size();
-    }
-    
     /**
      * Data table of a cache item. Used to retrieve a key, which has been selected.
      */

Modified: labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/CacheItemBean.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/CacheItemBean.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/CacheItemBean.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -6,28 +6,23 @@
 import java.util.Map;
 
 import org.jboss.cache.CacheException;
-import org.jboss.shotoku.cache.RenewableCacheItemData;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
 import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+import org.jboss.shotoku.cache.service.monitor.CacheAlert;
 
 public class CacheItemBean {
-	private RenewableCacheItemData<?> cacheItem;
+	private RenewableCacheItemOperations<?> cacheItem;
 	private List<? extends Object> keysDuringUpdate;
 	private List<? extends Object> keysNotDuringUpdate;
 	private Map<Object, Long> keysUpdatesAgo;
 	private RenewableCacheServiceMBean service;
 	
-	/**
-	 * If any of the keys where updated/ are in update for a time that is longer
-	 * than twice the interval of this cache item.
-	 */
-	private boolean alerted;
-	
 	private int newId;
 	private long newInterval;
 	
 	private AdminBean adminBean;
 	
-	public CacheItemBean(RenewableCacheItemData<?> cacheItem, RenewableCacheServiceMBean service, AdminBean adminBean) {
+	public CacheItemBean(RenewableCacheItemOperations<?> cacheItem, RenewableCacheServiceMBean service, AdminBean adminBean) {
 		this.cacheItem = cacheItem;
 		this.service = service;
 		
@@ -39,15 +34,10 @@
 		
 		Map<?, Long> keysUpdates = cacheItem.getKeysUpdates();		
 		long now = System.currentTimeMillis();
-		long maxKeyUpdateAgo = 0;
 		keysUpdatesAgo = new HashMap<Object, Long>();
 		for (Object key : keysUpdates.keySet()) {
 			long lastKeyUpdate = (now-keysUpdates.get(key));
 			keysUpdatesAgo.put(key, lastKeyUpdate/1000);
-			
-			if (lastKeyUpdate > maxKeyUpdateAgo) {
-				maxKeyUpdateAgo = lastKeyUpdate;
-			}
 		}
 		
 		//
@@ -57,8 +47,6 @@
 			interval = service.getInterval();
 		}
 		
-		alerted = maxKeyUpdateAgo > (2*interval);
-		
 		//
 		
 		keysNotDuringUpdate = new ArrayList<Object>(keysUpdates.keySet());
@@ -66,9 +54,13 @@
 	}
 	
 	public String getName() {
-		return cacheItem.getClass().getName();
+		return cacheItem.getName();
 	}
 	
+	public String getInfo() {
+		return cacheItem.getInfo();
+	}
+	
 	public List<? extends Object> getKeysDuringUpdate() {
 		return keysDuringUpdate;
 	}
@@ -93,10 +85,10 @@
 		}
 	}
 	
-	public boolean isAlerted() {
-		return alerted;
+	public List<CacheAlert> getAlerts() {
+		return adminBean.getMonitorBean().getMonitor().getAlertsForCacheItem(cacheItem);
 	}
-	
+
 	public int getId() {
 		return cacheItem.getId();
 	}

Added: labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/MonitorBean.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/MonitorBean.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-admin/src/java/org/jboss/shotoku/cache/admin/MonitorBean.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,113 @@
+package org.jboss.shotoku.cache.admin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
+import org.jboss.shotoku.cache.service.monitor.DummyRenewableCacheMonitorService;
+import org.jboss.shotoku.cache.service.monitor.RenewableCacheMonitorServiceMBean;
+import org.jboss.shotoku.tools.CacheTools;
+
+public class MonitorBean {
+	private RenewableCacheMonitorServiceMBean monitor;
+	
+	private boolean monitorAvailable;
+	private String monitorMbeanName;
+	
+	public RenewableCacheMonitorServiceMBean getMonitor() {
+		if (monitor == null) {
+			String mbean = getMonitorMbeanName();
+			if (mbean == null) {
+				mbean = CacheTools.DEFAULT_CACHE_MONITOR_MBEAN;
+			}
+			
+			try {
+				monitor = (RenewableCacheMonitorServiceMBean) CacheTools.getService(mbean, RenewableCacheMonitorServiceMBean.class);
+				monitorAvailable = true;
+			} catch (Exception e) {
+				monitor = new DummyRenewableCacheMonitorService();
+				monitorAvailable = false;
+			}
+		}
+		
+		return monitor;
+	}
+	
+	public String getMonitorMbeanName() {
+		return monitorMbeanName;
+	}
+
+	public void setMonitorMbeanName(String monitorMbeanName) {
+		this.monitorMbeanName = monitorMbeanName;
+	}
+	
+	public boolean getMonitorAvailable() {
+		getMonitor();
+		return monitorAvailable;
+	}
+	
+	private List<String> currentAlerts;
+	
+    public List<String> getCurrentAlerts() {
+    	if (currentAlerts == null) {
+    		currentAlerts = new ArrayList<String>();
+    		for (RenewableCacheItemOperations<?> rcid : getMonitor().getCacheItemsWithAlerts()) {
+    			currentAlerts.add(rcid.getName());
+    		}
+    	}
+    	
+    	return currentAlerts;
+    }
+    
+    public int getCurrentAlertsSize() {
+    	return getCurrentAlerts().size();
+    }
+    
+    public String clearAlerts() {
+    	getMonitor().clearAlerts();
+    	currentAlerts = null;
+    	return null;
+    }
+    
+    /*
+     * Configuration
+     */
+    
+    private long newInterval;
+    private int newMaximumNumberOfAlerts;
+    private int newUpdateAlertIntervalMultiplier;
+    
+    public long getInterval() {
+    	return getMonitor().getInterval();
+    }
+    
+    public void setInterval(long interval) {
+    	newInterval = interval;
+    }
+    
+    public int getMaximumNumberOfAlerts() {
+    	return getMonitor().getMaximumNumberOfAlerts();
+    }
+    
+    public void setMaximumNumberOfAlerts(int maximumNumberOfAlerts) {
+    	newMaximumNumberOfAlerts = maximumNumberOfAlerts;
+    }
+    
+    public int getUpdateAlertIntervalMultiplier() {
+    	return getMonitor().getUpdateAlertIntervalMultiplier();
+    }
+    
+    public void setUpdateAlertIntervalMultiplier(int updateAlertIntervalMultiplier) {
+    	newUpdateAlertIntervalMultiplier = updateAlertIntervalMultiplier;
+    }
+    
+    public String updateServiceConfig() {
+    	getMonitor().setInterval(newInterval);
+    	getMonitor().setMaximumNumberOfAlerts(newMaximumNumberOfAlerts);
+    	getMonitor().setUpdateAlertIntervalMultiplier(newUpdateAlertIntervalMultiplier);
+    
+    	CacheFacesTools.addTimedFacesMessage("Monitor configuration changed successfully.");
+    	
+    	return null;
+    }
+}

Modified: labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/WEB-INF/faces-config.xml
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/WEB-INF/faces-config.xml	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/WEB-INF/faces-config.xml	2007-08-26 09:08:09 UTC (rev 14574)
@@ -12,5 +12,19 @@
 			<property-name>mbeanName</property-name>
 			<null-value/>
 		</managed-property>
+		<managed-property>
+			<property-name>monitorBean</property-name>
+			<value>#{monitor}</value>
+		</managed-property>
 	</managed-bean>
+	
+	<managed-bean>
+		<managed-bean-name>monitor</managed-bean-name>
+		<managed-bean-class>org.jboss.shotoku.cache.admin.MonitorBean</managed-bean-class>
+		<managed-bean-scope>request</managed-bean-scope>
+		<managed-property>
+			<property-name>monitorMbeanName</property-name>
+			<null-value/>
+		</managed-property>
+	</managed-bean>
 </faces-config>
\ No newline at end of file

Modified: labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/pages/admin.jsp
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/pages/admin.jsp	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-admin/src/web/pages/admin.jsp	2007-08-26 09:08:09 UTC (rev 14574)
@@ -56,6 +56,7 @@
 						</h:panelGrid>
 					</rich:simpleTogglePanel>
 				
+					<h:panelGroup>
 					<rich:simpleTogglePanel switchType="client" label="Configuration">
 					<h:form>
 					<a4j:region id="AdminServiceSubmit">
@@ -82,6 +83,41 @@
 					</a4j:region>
 					</h:form>
 					</rich:simpleTogglePanel>
+					
+					<rich:simpleTogglePanel switchType="client" label="Monitor configuration" opened="false"
+						style="margin-top: 5px;">
+					<h:form>
+					<a4j:region id="MonitorServiceSubmit">
+						<h:panelGrid columns="2" columnClasses="left_text,right_text">
+							<h:outputText value="Interval: "/>
+							<h:inputText value="#{monitor.interval}" id="MonitorInterval" required="true">
+								<f:validateLongRange minimum="1000" />
+							</h:inputText>
+							
+							<h:outputText value="Max. number of alerts: "/>
+							<h:inputText value="#{monitor.maximumNumberOfAlerts}" id="MonitorMaxAlerts" required="true">
+								<f:validateLongRange maximum="100" minimum="0" />
+							</h:inputText>
+							
+							<h:outputText value="Update alert multiplier: "/>
+							<h:inputText value="#{monitor.updateAlertIntervalMultiplier}" id="MonitorUpdateAlertMultiplier" 
+								required="true">
+								<f:validateLongRange minimum="2" />
+							</h:inputText>
+							
+							<h:outputText value="" />
+							<a4j:commandButton value="Submit" action="#{monitor.updateServiceConfig}" 
+								reRender="monitorServiceMessages" />
+						</h:panelGrid>
+						
+						<h:panelGroup id="monitorServiceMessages">
+							<a4j:status startText="Sending ..." stopText="" for="MonitorServiceSubmit" />
+							<h:messages showDetail="true" />
+						</h:panelGroup>
+					</a4j:region>
+					</h:form>
+					</rich:simpleTogglePanel>
+					</h:panelGroup>
 			</h:panelGrid>
 			
 			<rich:panel styleClass="header_panel" id="cacheitem_messages">
@@ -90,13 +126,21 @@
 					<h:messages showDetail="true" />
 				</h:panelGroup>
 				<h:panelGroup id="alerts" styleClass="header_messages">
-					<h:panelGroup rendered="#{admin.currentAlertsSize > 0}">
+					<h:panelGroup rendered="#{monitor.currentAlertsSize > 0}">
+						<h:form>
+						<a4j:region id="ClearAlertsSubmit" renderRegionOnly="false">
 						<rich:panel styleClass="alert_panel">
 							<h:outputText value="Current alerts:" styleClass="alert" />
-							<rich:dataList var="alert" value="#{admin.currentAlerts}">
+							<rich:dataList var="alert" value="#{monitor.currentAlerts}">
 								<h:outputText value="#{alert}" />
 							</rich:dataList>
+							<a4j:commandLink value="Clear all alerts" action="#{monitor.clearAlerts}" limitToList="true" 
+								reRender="alerts,cacheitem_information" ajaxSingle="true" />
 						</rich:panel>
+						</a4j:region>
+						
+						<a4j:status for="ClearAlertsSubmit" startText="Wait ..." stopText="" />
+						</h:form>
 					</h:panelGroup>
 				</h:panelGroup>
 			</rich:panel>
@@ -104,23 +148,27 @@
 			<rich:simpleTogglePanel switchType="client" opened="true" label="Please note" styleClass="note_panel">
 				<f:verbatim>
 					<ul>
-						<li>only cache items which contain keys that should be updated/ are in update for
-							a time that is at least 2*interval are expanded</li>
+						<li>only cache items which contain alerts are expanded</li>
 						<li>all changes in the settings will be lost on AS restart; remember to modify
 							the configuration files</li>
 						<li>checking if there are any new cache items requires a page refresh</li>
+						<li>a 0 interval in cache item configuration means that the cache item is updated on each
+							service update</li>
 					</ul>
 				</f:verbatim>
 			</rich:simpleTogglePanel>
 			
 			<rich:dataGrid columns="1" var="cacheItem" value="#{admin.cacheItems}" styleClass="cacheitem_table" id="cacheitems">
 					<rich:simpleTogglePanel switchType="client" label="#{cacheItem.name}"
-						opened="#{cacheItem.alerted}">
+						opened="#{cacheItem.alerts != null}">
 						<h:panelGrid columns="2">
 							<rich:simpleTogglePanel switchType="client" label="Information">
 								<h:panelGrid columns="2" columnClasses="left_text,right_text" id="cacheitem_information">
 									<h:outputText value="Name: "/>
 									<h:outputText value="#{cacheItem.name}" />
+									
+									<h:outputText value="Info: "/>
+									<h:outputText value="#{cacheItem.info}" />
 								
 									<h:outputText value="FQN: "/>
 									<h:outputText value="#{cacheItem.fqn}" />		
@@ -128,10 +176,13 @@
 									<h:outputText value="FQN keys count: "/>
 									<h:outputText value="#{cacheItem.fqnKeysCount}" />		
 								 
-									<h:outputText rendered="#{cacheItem.alerted}" styleClass="alert"
-										value="Alert: "/>
-									<h:outputText rendered="#{cacheItem.alerted}" styleClass="alert"
-										value="Some keys are not updated/ are in update for a too long time" />					
+									<h:outputText rendered="#{cacheItem.alerts != null}" styleClass="alert"
+										value="Alert(s): "/>
+									<rich:dataList rendered="#{cacheItem.alerts != null}" styleClass="alert"
+										value="#{cacheItem.alerts}" var="alert">
+										<h:outputText value="#{alert.timeFormatted} (#{alert.key}) #{alert.description}" />
+										<h:outputText rendered="#{alert.cause != null}" value="Show cause" />
+									</rich:dataList>					
 								</h:panelGrid>
 							</rich:simpleTogglePanel>
 							

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItem.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItem.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItem.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -35,8 +35,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import javax.management.MalformedObjectNameException;
-
 /**
  * Extend this class if you want to store objects in a cache that
  * will be updated on a regular intervals of time, by a service daemon
@@ -58,12 +56,11 @@
  * 
  * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
  */
-public abstract class RenewableCacheItem<K, T> implements RenewableCacheItemData<K> {
+public abstract class RenewableCacheItem<K, T> implements RenewableCacheItemOperations<K> {
 	private final Logger log = Logger.getLogger(RenewableCacheItem.class);
 	
     private Fqn fqn;
     private long interval;
-    private long timeout;
     private String mbeanName;
     private int id;
     
@@ -78,6 +75,10 @@
      * some keys may be waiting in a queue.
      */
     private ConcurrentSet<K> keysDuringUpdate;
+    /**
+     * Exceptions whih occured on last update of keys.
+     */
+    private ConcurrentMap<K, Throwable> keysExceptions;
     
     private RenewableCacheServiceMBean service;
 
@@ -97,11 +98,8 @@
      * the service update thread interval. The interval should be given in milliseconds.
      * If it is 0, the {@link #update()} method will be executed on every service
      * thread update.
-     * 
-     * @param timeout How long, at a maximum, an update method for a key can last. If this
-     * value is non-zero, and is exceeded, a monitoring thread will interupt the update.
      */
-    public RenewableCacheItem(Fqn fqn, String mbeanName, long interval, long timeout) {
+    public RenewableCacheItem(Fqn fqn, String mbeanName, long interval) {
     	if (mbeanName == null) {
     		mbeanName = CacheTools.DEFAULT_RENEWABLE_CACHE_MBEAN;
     	}
@@ -109,11 +107,11 @@
     	this.mbeanName = mbeanName;
     	
     	this.interval = interval;
-        this.timeout = timeout;
     	
         keysUpdates = new ConcurrentHashMap<K, Long>();
         keysDuringUpdate = new ConcurrentHashSet<K>();
         keysInUpdate = new ConcurrentHashSet<K>();
+        keysExceptions = new ConcurrentHashMap<K, Throwable>();
     	
         id = CacheTools.getNextId();
         
@@ -133,7 +131,7 @@
      * update and there will be no limit on the length of a key update.
      */
     public RenewableCacheItem() {
-        this(null, null, 0, 0);
+        this(null, null, 0);
     }
     
     /**
@@ -148,11 +146,12 @@
 					keysDuringUpdate.clear();
 					
 					try {
-						service = CacheTools.getService(mbeanName);
-					} catch (MalformedObjectNameException e) {
+						service = (RenewableCacheServiceMBean) 
+						CacheTools.getService(mbeanName, RenewableCacheServiceMBean.class);
+					} catch (Exception e) {
 						log.error("No RenewableCacheService bound to "
 								+ mbeanName + " in cache item "
-								+ this.getClass() + "!");
+								+ getName() + "!");
 						return;
 					}
 
@@ -207,25 +206,9 @@
 	public String getMbeanName() {
 		return mbeanName;
 	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see org.jboss.shotoku.cache.RenewableCacheItemConfiguration#getTimeout()
-	 */
-	public synchronized long getTimeout() {
-		return timeout;
-	}
 
 	/*
 	 * (non-Javadoc)
-	 * @see org.jboss.shotoku.cache.RenewableCacheItemConfiguration#setTimeout(long)
-	 */
-	public synchronized void setTimeout(long timeout) {
-		this.timeout = timeout;
-	}
-
-	/*
-	 * (non-Javadoc)
 	 * @see org.jboss.shotoku.cache.RenewableCacheItemConfiguration#getKeysDuringUpdate()
 	 */
 	public ConcurrentSet<K> getKeysDuringUpdate() {
@@ -240,9 +223,37 @@
 		return keysUpdates;
 	}
 	
+	/*
+	 * (non-Javadoc)
+	 * @see org.jboss.shotoku.cache.RenewableCacheItemOperations#getKeysExceptions()
+	 */
+	public ConcurrentMap<K, Throwable> getKeysExceptions() {
+		return keysExceptions;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.jboss.shotoku.cache.RenewableCacheItemOperations#getId()
+	 */
 	public int getId() {
 		return id;
 	}
+    
+    /*
+     * (non-Javadoc)
+     * @see org.jboss.shotoku.cache.RenewableCacheItemData#getInfo()
+     */
+    public String getInfo() {
+    	return "";
+    }
+    
+    /*
+     * (non-Javadoc)
+     * @see org.jboss.shotoku.cache.RenewableCacheItemData#getName()
+     */
+    public String getName() {
+    	return this.getClass().getName();
+    }
 
 	/**
      * Binds the given key with the given object in the associated TreeCache
@@ -312,7 +323,7 @@
         for (final K key : keysUpdates.keySet()) {
             if (now - keysUpdates.get(key) >= interval) {
                 if (keysInUpdate.add(key)) {
-                    service.addUpdateThreadData(new UpdateThreadData() {
+                    service.addUpdateThreadData(new UpdateThreadData<K>(key, this) {
                         public void execute() {
                         	keysUpdates.put(key, System.currentTimeMillis());
                         	keysDuringUpdate.add(key);
@@ -338,8 +349,28 @@
     	keysInUpdate.remove(key);
     	keysDuringUpdate.remove(key);
     }
+    
+    /*
+     * (non-Javadoc)
+     * @see org.jboss.shotoku.cache.RenewableCacheItemOperations#reportUpdateOk(java.lang.Object)
+     */
+    public void reportUpdateOk(K key) {
+		
+	}
 
-    /**
+    /*
+     * (non-Javadoc)
+     * @see org.jboss.shotoku.cache.RenewableCacheItemOperations#reportUpdateWithException(java.lang.Object, java.lang.Throwable)
+     */
+	public void reportUpdateWithException(K key, Throwable t) {
+		if (keysExceptions.put(key, t) == null) {
+			// There was no exception before.
+			log.error("Update of cache item " + getName() + " for key " + key + " threw an exception. Suppressing " +
+					"subsequent exceptions.", t);
+		}
+	}
+
+	/**
      * Called by the service periodically to update the object held in the
      * cache.
      * If the object in the cache should be changed, the implementing

Deleted: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemData.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemData.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemData.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -1,110 +0,0 @@
-/******************************************************************************
- * JBoss, a division of Red Hat                                               *
- * Copyright 2006, Red Hat Middleware, LLC, and individual                    *
- * contributors as indicated by the @authors tag. See the                     *
- * copyright.txt in the distribution for a full listing of                    *
- * individual contributors.                                                   *
- *                                                                            *
- * This is free software; you can redistribute it and/or modify it            *
- * under the terms of the GNU Lesser General Public License as                *
- * published by the Free Software Foundation; either version 2.1 of           *
- * the License, or (at your option) any later version.                        *
- *                                                                            *
- * This software 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           *
- * Lesser General Public License for more details.                            *
- *                                                                            *
- * You should have received a copy of the GNU Lesser General Public           *
- * License along with this software; if not, write to the Free                *
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA         *
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.                   *
- ******************************************************************************/
-package org.jboss.shotoku.cache;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.cache.Fqn;
-import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
-
-/**
- * Configuration data of a cache item.
- * @param <K> Type of the key of the objects held in cache. The keys
- * should bahave well as map keys (most probably, the hashCode() and
- * equals() methods should be overriden).
- * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
- */
-public interface RenewableCacheItemData<K> {
-	/**
-	 * 
-	 * @return A fqn of a TreeCache node associated with this cache item. This is a node in which
-	 * data will be kept.
-	 */
-	public Fqn getFqn();
-	
-	/**
-	 * 
-	 * @return Interval at which the update operation will be executed.
-     * Effectively, the interval will be rounded to the nearest multiplicity of
-     * the service update thread interval. The interval should be given in milliseconds.
-     * If it is 0, the {@link RenewableCacheItem#update()} method will be executed on every service
-     * thread update.
-	 */
-	public long getInterval();
-	/**
-	 * 
-	 * @param interval Interval at which the update operation will be executed.
-     * Effectively, the interval will be rounded to the nearest multiplicity of
-     * the service update thread interval. The interval should be given in milliseconds.
-     * If it is 0, the {@link RenewableCacheItem#update()} method will be executed on every service
-     * thread update.
-	 */
-	public void setInterval(long interval);
-	
-	/**
-	 * 
-	 * @return How long, at a maximum, an update method for a key can last. If this
-     * value is non-zero, and is exceeded, a monitoring thread will interupt the update.
-	 */
-	public long getTimeout();
-	/**
-	 * 
-	 * @param timeout How long, at a maximum, an update method for a key can last. If this
-     * value is non-zero, and is exceeded, a monitoring thread will interupt the update.
-	 */
-	public void setTimeout(long timeout);
-	
-	/**
-	 * 
-	 * @return Name of an mbean implementing the {@link RenewableCacheServiceMBean} interface, associated
-	 * with this cache item.
-	 */
-	public String getMbeanName();
-	
-	/**
-	 * 
-	 * @return A map of keys, which are handeled by this cache item, and corresponding last
-	 * update times.
-	 */
-	public Map<K, Long> getKeysUpdates();
-	
-	/**
-	 * 
-	 * @return A set of keys, which are currently being updated.
-	 */
-	public Set<K> getKeysDuringUpdate();
-	
-	/**
-	 * 
-	 * @return A unique id of this instance of cache items.
-	 */
-	public int getId();
-	
-	/**
-	 * Resets the given key, that is, it's update status. Hence, if a thread updating a key
-	 * locks for some reason, it is possible to resume updates of this thread. Use with caution.
-	 * @param key Key, which update status should be reset.
-	 */
-	public void resetKey(Object key);
-}

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemOperations.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemOperations.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/RenewableCacheItemOperations.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,129 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat                                               *
+ * Copyright 2006, Red Hat Middleware, LLC, and individual                    *
+ * contributors as indicated by the @authors tag. See the                     *
+ * copyright.txt in the distribution for a full listing of                    *
+ * individual contributors.                                                   *
+ *                                                                            *
+ * This is free software; you can redistribute it and/or modify it            *
+ * under the terms of the GNU Lesser General Public License as                *
+ * published by the Free Software Foundation; either version 2.1 of           *
+ * the License, or (at your option) any later version.                        *
+ *                                                                            *
+ * This software 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           *
+ * Lesser General Public License for more details.                            *
+ *                                                                            *
+ * You should have received a copy of the GNU Lesser General Public           *
+ * License along with this software; if not, write to the Free                *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA         *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.                   *
+ ******************************************************************************/
+package org.jboss.shotoku.cache;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.cache.Fqn;
+import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+
+/**
+ * Configuration nad other operations on a cache item ({@link RenewableCacheItem}).
+ * @param <K> Type of the key of the objects held in cache. The keys
+ * should bahave well as map keys (most probably, the hashCode() and
+ * equals() methods should be overriden).
+ * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
+ */
+public interface RenewableCacheItemOperations<K> {
+	/**
+	 * 
+	 * @return A fqn of a TreeCache node associated with this cache item. This is a node in which
+	 * data will be kept.
+	 */
+	public Fqn getFqn();
+	
+	/**
+	 * 
+	 * @return Interval at which the update operation will be executed.
+     * Effectively, the interval will be rounded to the nearest multiplicity of
+     * the service update thread interval. The interval should be given in milliseconds.
+     * If it is 0, the {@link RenewableCacheItem#update()} method will be executed on every service
+     * thread update.
+	 */
+	public long getInterval();
+	/**
+	 * 
+	 * @param interval Interval at which the update operation will be executed.
+     * Effectively, the interval will be rounded to the nearest multiplicity of
+     * the service update thread interval. The interval should be given in milliseconds.
+     * If it is 0, the {@link RenewableCacheItem#update()} method will be executed on every service
+     * thread update.
+	 */
+	public void setInterval(long interval);
+	
+	/**
+	 * 
+	 * @return Name of an mbean implementing the {@link RenewableCacheServiceMBean} interface, associated
+	 * with this cache item.
+	 */
+	public String getMbeanName();
+	
+	/**
+	 * 
+	 * @return A map of keys, which are handeled by this cache item, and corresponding last
+	 * update times.
+	 */
+	public Map<K, Long> getKeysUpdates();
+	
+	/**
+	 * 
+	 * @return A set of keys, which are currently being updated.
+	 */
+	public Set<K> getKeysDuringUpdate();
+	
+	/**
+	 * 
+	 * @return A map of keys, in which an exception occured during an update.
+	 */
+	public Map<K, Throwable> getKeysExceptions();
+	
+	/**
+	 * 
+	 * @return A unique id of this instance of cache item.
+	 */
+	public int getId();
+	
+	/**
+	 * Resets the given key, that is, it's update status. Hence, if a thread updating a key
+	 * locks for some reason, it is possible to resume updates of this thread. Use with caution.
+	 * @param key Key, which update status should be reset.
+	 */
+	public void resetKey(Object key);
+	
+	/**
+	 * 
+	 * @return Additional information about the state of this object. Defaults to an empty string, but
+	 * {@link RenewableCacheItem} implementations can override this method.
+	 */
+	public String getInfo();
+	
+	/**
+	 * 
+	 * @return Name of this {@link RenewableCacheItem}. Usually the fully qualified class name.
+	 */
+	public String getName();
+	
+	/**
+	 * Reports that an update of a key ended wihtout any exceptions.
+	 * @param key Key which has been updated.
+	 */
+	public void reportUpdateOk(K key);
+	
+	/**
+	 * Reports that an update of a key ended with an exception.
+	 * @param key Key which has been updated.
+	 * @param t Exception which was thrown during the update.
+	 */
+	public void reportUpdateWithException(K key, Throwable t);
+}

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/SignalExitUpdateThreadData.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/SignalExitUpdateThreadData.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/SignalExitUpdateThreadData.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -27,7 +27,11 @@
  * 
  * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
  */
-public class SignalExitUpdateThreadData extends UpdateThreadData {
+public class SignalExitUpdateThreadData<K> extends UpdateThreadData<K> {
+	public SignalExitUpdateThreadData() {
+		super(null, null);
+	}
+
 	@Override
 	public void execute() {
 	}

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThread.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThread.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThread.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -34,10 +34,10 @@
 public class UpdateThread extends Thread {
     private static final Logger log = Logger.getLogger(UpdateThread.class);
     
-    private BlockingQueue<UpdateThreadData> queue;
+    private BlockingQueue<UpdateThreadData<?>> queue;
     private RenewableCacheServiceMBean service;
 
-    public UpdateThread(RenewableCacheServiceMBean service, LinkedBlockingQueue<UpdateThreadData> queue) {
+    public UpdateThread(RenewableCacheServiceMBean service, LinkedBlockingQueue<UpdateThreadData<?>> queue) {
         this.queue = queue;
         this.service = service;
 
@@ -48,7 +48,7 @@
     	service.reportThreadNew();
     	
         while (true) {
-            UpdateThreadData data;
+            UpdateThreadData<?> data;
             try {
                 data = queue.take();
                 service.reportThreadBusy();
@@ -56,15 +56,16 @@
                 long start = System.currentTimeMillis();
                 service.getStatistics().addPacketWaitingTime(start - data.getCreateTime());
                 
-                if (data instanceof SignalExitUpdateThreadData) {
+                if (data instanceof SignalExitUpdateThreadData<?>) {
                 	break;
                 }
                 
                 try {
                     data.execute();
+                    data.updateOk();
                     service.getStatistics().addPacketProcessingTime(System.currentTimeMillis() - start, false);
                 } catch (Throwable t) {
-                    log.error("Exception while executing an update thread data.", t);
+                	data.updateWithException(t);
                     service.getStatistics().addPacketProcessingTime(System.currentTimeMillis() - start, true);
                 }
                 

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThreadData.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThreadData.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/UpdateThreadData.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -23,19 +23,34 @@
 package org.jboss.shotoku.cache;
 
 /**
- * Function that should be executed by an update thread.
+ * Function that should be executed by an update thread; updates an associated
+ * key in a cache item.
  * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
  */
-public abstract class UpdateThreadData {
+public abstract class UpdateThreadData<K> {
 	private long createTime;
 	
-    public UpdateThreadData() {
+	private K key;
+	private RenewableCacheItemOperations<K> cacheItem;
+	
+    public UpdateThreadData(K key, RenewableCacheItemOperations<K> cacheItem) {
 		createTime = System.currentTimeMillis();
+		
+		this.key = key;
+		this.cacheItem = cacheItem;
 	}
 
 	public long getCreateTime() {
 		return createTime;
 	}
 
+	public void updateOk() {
+		cacheItem.reportUpdateOk(key);
+	}
+	
+	public void updateWithException(Throwable t) {
+		cacheItem.reportUpdateWithException(key, t);
+	}
+	
 	public abstract void execute();
 }

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/DummyRenewableCacheService.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/DummyRenewableCacheService.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/DummyRenewableCacheService.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -7,7 +7,7 @@
 import org.jboss.cache.Fqn;
 import org.jboss.cache.TreeCacheMBean;
 import org.jboss.shotoku.cache.RenewableCacheItem;
-import org.jboss.shotoku.cache.RenewableCacheItemData;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
 import org.jboss.shotoku.cache.UpdateThreadData;
 
 /**
@@ -16,7 +16,7 @@
  * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
  */
 public class DummyRenewableCacheService implements RenewableCacheServiceMBean {
-	public void addUpdateThreadData(UpdateThreadData data) {
+	public void addUpdateThreadData(UpdateThreadData<?> data) {
 	}
 
 	public Fqn generateNextFqn() {
@@ -88,7 +88,7 @@
 	public void update() {
 	}
 
-	public Set<? extends RenewableCacheItemData<?>> getCacheItemsData() {
+	public Set<? extends RenewableCacheItemOperations<?>> getCacheItemsOperations() {
 		return null;
 	}
 

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/RenewableCacheServiceMBean.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/RenewableCacheServiceMBean.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/RenewableCacheServiceMBean.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -28,7 +28,7 @@
 import org.jboss.cache.Fqn;
 import org.jboss.cache.TreeCacheMBean;
 import org.jboss.shotoku.cache.RenewableCacheItem;
-import org.jboss.shotoku.cache.RenewableCacheItemData;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
 import org.jboss.shotoku.cache.UpdateThreadData;
 
 /**
@@ -45,7 +45,7 @@
 
     public Fqn generateNextFqn();
 
-    public void addUpdateThreadData(UpdateThreadData data);
+    public void addUpdateThreadData(UpdateThreadData<?> data);
     public int getCurrentQueueSize(); 
     
     public RenewableCacheStatistics getStatistics();
@@ -69,7 +69,7 @@
     public int getIdleThreadCount();
     public int getBusyThreadCount();
     
-    public Set<? extends RenewableCacheItemData<?>> getCacheItemsData();
+    public Set<? extends RenewableCacheItemOperations<?>> getCacheItemsOperations();
     
     public void update();
     

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlert.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlert.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlert.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,36 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+import org.jboss.shotoku.cache.RenewableCacheItem;
+
+/**
+ * Information about probably incorrect behaviour of cache items, collected
+ * by the monitoring thread.
+ * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
+ */
+public interface CacheAlert {
+	/**
+	 * 
+	 * @return Time on which the represented behaviour was observed.
+	 */
+	public long getTime();
+	/**
+	 * 
+	 * @return Time on which the represented behaviour was observed, formatted as a string.
+	 */
+	public String getTimeFormatted();
+	/**
+	 * 
+	 * @return Short description of the incorrect behaviour.
+	 */
+	public String getDescription();
+	/**
+	 * 
+	 * @return Possible/definite cause of the incorrect behaviour.
+	 */
+	public String getCause();
+	/**
+	 * 
+	 * @return {@link RenewableCacheItem} key, for which the incorrect behaviour occured.
+	 */
+	public Object getKey();
+}

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertFactory.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertFactory.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertFactory.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,15 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+public class CacheAlertFactory {
+	public static CacheAlert createAlertKeyNotUpdated(Object key) {
+		return new CacheAlertImpl(null, "Key hasn't been updated for a long time.", key);
+	}
+	
+	public static CacheAlert createAlertKeyTooLongInUpdate(Object key) {
+		return new CacheAlertImpl(null, "Key is too long in update.", key);
+	}
+	
+	public static CacheAlert createAlertKeyException(Object key, Throwable t) {
+		return new CacheAlertImpl(t.toString(), "An exception occured during key update.", key);
+	}
+}

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertImpl.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertImpl.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/CacheAlertImpl.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,75 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+
+/**
+ * 
+ * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
+ */
+public class CacheAlertImpl implements CacheAlert {
+	private long time;
+	private String cause;
+	private String description;
+	private Object key;
+	
+	public CacheAlertImpl(String cause, String description, Object key) {
+		super();
+		this.time = System.currentTimeMillis();
+		this.cause = cause;
+		this.description = description;
+		this.key = key;
+	}
+	
+	public String getCause() {
+		return cause;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public long getTime() {
+		return time;
+	}
+	
+	public Object getKey() {
+		return key;
+	}
+
+	public String getTimeFormatted() {
+		return DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date(getTime()));
+	}
+	
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((description == null) ? 0 : description.hashCode());
+		result = PRIME * result + ((key == null) ? 0 : key.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		final CacheAlertImpl other = (CacheAlertImpl) obj;
+		if (description == null) {
+			if (other.description != null)
+				return false;
+		} else if (!description.equals(other.description))
+			return false;
+		if (key == null) {
+			if (other.key != null)
+				return false;
+		} else if (!key.equals(other.key))
+			return false;
+		return true;
+	}
+}

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/DummyRenewableCacheMonitorService.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/DummyRenewableCacheMonitorService.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/DummyRenewableCacheMonitorService.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,66 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
+import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+
+public class DummyRenewableCacheMonitorService implements RenewableCacheMonitorServiceMBean {
+	public void clearAlerts() {
+	
+	}
+
+	public List<CacheAlert> getAlertsForCacheItem(RenewableCacheItemOperations<?> rcid) {
+		return null;
+	}
+
+	public Set<RenewableCacheItemOperations<?>> getCacheItemsWithAlerts() {
+		return new HashSet<RenewableCacheItemOperations<?>>();
+	}
+
+	public long getInterval() {
+		return 0;
+	}
+
+	public int getMaximumNumberOfAlerts() {
+		return 0;
+	}
+
+	public RenewableCacheServiceMBean getRenewableCacheService() {
+		return null;
+	}
+
+	public int getUpdateAlertIntervalMultiplier() {
+		return 0;
+	}
+
+	public void setInterval(long interval) {
+		
+	}
+
+	public void setMaximumNumberOfAlerts(int maximumNumberOfAlerts) {
+		
+	}
+
+	public void setRenewableCacheService(RenewableCacheServiceMBean renewableCacheService) {
+		
+	}
+
+	public void setUpdateAlertIntervalMultiplier(int updateAlertIntervalMultiplier) {
+		
+	}
+
+	public void start() {
+		
+	}
+
+	public void stop() {
+		
+	}
+
+	public void update() {
+		
+	}
+}

Added: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorServiceMBean.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorServiceMBean.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorServiceMBean.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,75 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
+import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+
+/**
+ * 
+ * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
+ */
+public interface RenewableCacheMonitorServiceMBean {
+	public RenewableCacheServiceMBean getRenewableCacheService();
+	public void setRenewableCacheService(RenewableCacheServiceMBean renewableCacheService);
+	
+	/**
+	 * 
+	 * @return Interval at which cache items will be checked, if there are no errors.
+	 */
+	public long getInterval();
+	/**
+	 * 
+	 * @param interval Interval at which cache items will be checked, if there are no errors.
+	 */
+	public void setInterval(long interval);
+	
+	/**
+	 * 
+	 * @return Maximum number of alerts stored. After this number is exceeded, no new alerts
+	 * are recorded.
+	 */
+	public int getMaximumNumberOfAlerts();
+	/**
+	 * 
+	 * @param Maximum number of alerts stored. After this number is exceeded, no new alerts
+	 * are recorded.
+	 */
+	public void setMaximumNumberOfAlerts(int maximumNumberOfAlerts);
+	
+	/**
+	 * 
+	 * @return How many times the interval of a cache item must be exceeded, before an 
+	 * "key not updated" or "key too long in update" alert is issued.
+	 */
+	public int getUpdateAlertIntervalMultiplier();
+	/**
+	 * 
+	 * @param updateAlertIntervalMultiplier How many times the interval of a cache item must be exceeded, before an 
+	 * "key not updated" or "key too long in update" alert is issued.
+	 */
+	public void setUpdateAlertIntervalMultiplier(int updateAlertIntervalMultiplier);
+	
+	public void update();
+    
+    public void start();
+    public void stop();
+    
+    /**
+     * 
+     * @param rcid {@link RenewableCacheItem} for which to get alerts.
+     * @return A list of alerts for the given {@link RenewableCacheItem}, sorted from the
+     * newest alert, or null is there are no alerts for the given cache item.
+     */
+    public List<CacheAlert> getAlertsForCacheItem(RenewableCacheItemOperations<?> rcid);
+    /**
+     * Clears all alerts.
+     */
+    public void clearAlerts();
+    /**
+     * 
+     * @return A set of {@link RenewableCacheItemOperations}, for which there are any alerts.
+     */
+    public Set<RenewableCacheItemOperations<?>> getCacheItemsWithAlerts();
+}

Modified: labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/tools/CacheTools.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/tools/CacheTools.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-base/src/java/org/jboss/shotoku/tools/CacheTools.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -27,6 +27,7 @@
 import org.jboss.mx.util.MBeanProxyExt;
 import org.jboss.mx.util.MBeanServerLocator;
 import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+import org.jboss.shotoku.cache.service.monitor.RenewableCacheMonitorServiceMBean;
 
 /**
  * Utility, helper functions used internally.
@@ -45,15 +46,20 @@
 	public static final String DEFAULT_RENEWABLE_CACHE_MBEAN = "shotoku:service=RenewableCache";
 	
 	/**
+	 * Name of the default {@link RenewableCacheMonitorServiceMBean} mbean.
+	 */
+	public static final String DEFAULT_CACHE_MONITOR_MBEAN = "shotoku:service=RenewableCacheMonitor";
+	
+	/**
 	 * Gets a reference to an mbean with the given name.
 	 * @param mbeanName Name of the mbean to get.
+	 * @param c Class of the mbean to get.
 	 * @return A reference to the mbean.
 	 * @throws MalformedObjectNameException
 	 */
-    public static RenewableCacheServiceMBean getService(String mbeanName) throws MalformedObjectNameException {
-		return (RenewableCacheServiceMBean) MBeanProxyExt.create(
-				RenewableCacheServiceMBean.class, mbeanName,
-				MBeanServerLocator.locate());
+    public static Object getService(String mbeanName,
+    		Class<?> c) throws MalformedObjectNameException {
+		return MBeanProxyExt.create(c, mbeanName, MBeanServerLocator.locate());
 	}
 
     /**

Modified: labs/shotoku/trunk/shotoku-cache/cache-service/src/etc/META-INF/jboss-service.xml
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-service/src/etc/META-INF/jboss-service.xml	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-service/src/etc/META-INF/jboss-service.xml	2007-08-26 09:08:09 UTC (rev 14574)
@@ -12,6 +12,17 @@
 			shotoku:service=TreeCache
 		</depends>
 	</mbean>
+	
+	<mbean code="org.jboss.shotoku.cache.service.monitor.RenewableCacheMonitorService"
+		name="shotoku:service=RenewableCacheMonitor">
+		<attribute name="Interval">30000</attribute>
+		<attribute name="MaximumNumberOfAlerts">20</attribute>
+		<attribute name="UpdateAlertIntervalMultiplier">2</attribute>
+		<depends optional-attribute-name="RenewableCacheService"
+			proxy-type="attribute">
+			shotoku:service=RenewableCache
+		</depends>
+	</mbean>
 
 	<mbean code="org.jboss.cache.TreeCache"
 		name="shotoku:service=TreeCache">

Modified: labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/RenewableCacheService.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/RenewableCacheService.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/RenewableCacheService.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -26,7 +26,7 @@
 import org.jboss.cache.Fqn;
 import org.jboss.cache.TreeCacheMBean;
 import org.jboss.shotoku.cache.RenewableCacheItem;
-import org.jboss.shotoku.cache.RenewableCacheItemData;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
 import org.jboss.shotoku.cache.SignalExitUpdateThreadData;
 import org.jboss.shotoku.cache.UpdateThread;
 import org.jboss.shotoku.cache.UpdateThreadData;
@@ -114,7 +114,7 @@
 	 * 
 	 */
 
-	public void startUpdateThread() {
+	private void startUpdateThread() {
         Thread ut = new Thread() {
             {
                 setDaemon(true);
@@ -126,7 +126,7 @@
                         sleep(getInterval());
                     } catch (InterruptedException e) {
                     	// Quit.
-                        log.info("Stopping update thread for " + getName() + " (interrupted).");
+                        log.info("Stopping update thread (interrupted).");
                         return;
                     }
 
@@ -134,7 +134,7 @@
                         update();
                     } catch (Throwable t) {
                         // Making sure that an exception won't stop the thread.
-                        log.error("Update method for " + getName() + " threw an exception.", t);
+                        log.error("Update method threw an exception.", t);
                     }
 
                     setLastUpdate(Calendar.getInstance().getTimeInMillis());
@@ -177,7 +177,7 @@
     	}
     }
    
-    public Set<? extends RenewableCacheItemData<?>> getCacheItemsData() {
+    public Set<? extends RenewableCacheItemOperations<?>> getCacheItemsOperations() {
 		return cacheItems;
 	}
 
@@ -195,8 +195,8 @@
      * Update threads management.
      */
 
-    private final LinkedBlockingQueue<UpdateThreadData> updateThreadDataQueue =
-        new LinkedBlockingQueue<UpdateThreadData>();
+    private final LinkedBlockingQueue<UpdateThreadData<?>> updateThreadDataQueue =
+        new LinkedBlockingQueue<UpdateThreadData<?>>();
     
     private int updateThreadCount;
     private int busyThreads;
@@ -204,7 +204,7 @@
     
     private final Object threadCounterSynchronizer = new Object();
 
-    public void addUpdateThreadData(UpdateThreadData data) {
+    public void addUpdateThreadData(UpdateThreadData<?> data) {
     	updateThreadDataQueue.offer(data);
     }
     
@@ -220,7 +220,7 @@
 			}
 		} else if (n < updateThreadCount) {
 			for (int i = updateThreadCount; i > n; i--) {
-				updateThreadDataQueue.offer(new SignalExitUpdateThreadData());
+				updateThreadDataQueue.offer(new SignalExitUpdateThreadData<Object>());
 			}
 		}
 

Added: labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorService.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorService.java	                        (rev 0)
+++ labs/shotoku/trunk/shotoku-cache/cache-service/src/java/org/jboss/shotoku/cache/service/monitor/RenewableCacheMonitorService.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -0,0 +1,208 @@
+package org.jboss.shotoku.cache.service.monitor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.jboss.shotoku.cache.RenewableCacheItemOperations;
+import org.jboss.shotoku.cache.service.RenewableCacheServiceMBean;
+
+/**
+ * 
+ * @author <a href="mailto:adam.warski at jboss.org">Adam Warski</a>
+ */
+public class RenewableCacheMonitorService implements RenewableCacheMonitorServiceMBean {
+	private final static Logger log = Logger.getLogger(RenewableCacheMonitorServiceMBean.class);
+	
+	private long interval;
+	private RenewableCacheServiceMBean renewableCacheService;
+	private int maximumNumberOfAlerts;
+	private int updateAlertIntervalMultiplier;
+
+	public long getInterval() {
+		return interval;
+	}
+
+	public void setInterval(long interval) {
+		this.interval = interval;
+	}
+
+	public int getMaximumNumberOfAlerts() {
+		return maximumNumberOfAlerts;
+	}
+
+	public void setMaximumNumberOfAlerts(int maximumNumberOfAlerts) {
+		this.maximumNumberOfAlerts = maximumNumberOfAlerts;
+	}
+
+	public RenewableCacheServiceMBean getRenewableCacheService() {
+		return renewableCacheService;
+	}
+
+	public void setRenewableCacheService(
+			RenewableCacheServiceMBean renewableCacheService) {
+		this.renewableCacheService = renewableCacheService;
+	}
+
+	public int getUpdateAlertIntervalMultiplier() {
+		return updateAlertIntervalMultiplier;
+	}
+
+	public void setUpdateAlertIntervalMultiplier(int updateAlertIntervalMultiplier) {
+		this.updateAlertIntervalMultiplier = updateAlertIntervalMultiplier;
+	}
+	
+	//
+
+	private Thread monitorThread;
+	
+	public void start() {
+		monitorThread = new Thread() {
+            {
+                setDaemon(true);
+            }
+
+            public void run() {
+                while (true) {
+                    try {
+                        sleep(getInterval());
+                    } catch (InterruptedException e) {
+                    	// Quit.
+                        log.info("Stopping monitor thread (interrupted).");
+                        return;
+                    }
+
+                    try {
+                        update();
+                    } catch (Throwable t) {
+                        // Making sure that an exception won't stop the thread.
+                        log.error("Monitor update method threw an exception.", t);
+                    }
+                }
+            }
+        };
+        
+        log.info("Starting monitor thread.");
+        monitorThread.start();
+	}
+
+	public void stop() {
+		if (monitorThread != null) {
+			log.info("Signalling monitor thread to stop.");
+			monitorThread.interrupt();
+		}
+	}
+
+	//
+	
+	private Set<RenewableCacheItemOperations<?>> cacheItemsWithAlerts = new HashSet<RenewableCacheItemOperations<?>>();
+	private Map<RenewableCacheItemOperations<?>, Set<CacheAlert>> alertsForCacheItems =
+		new HashMap<RenewableCacheItemOperations<?>, Set<CacheAlert>>();
+	
+	private int currentNumberOfAlerts;
+	
+	private synchronized int getCurrentNumberOfAlerts() {
+		return currentNumberOfAlerts;
+	}
+	
+	public void update() {
+		long now = System.currentTimeMillis();
+		
+		if (getCurrentNumberOfAlerts() == getMaximumNumberOfAlerts()) {
+			// We can't add an alert anyway.
+			return;
+		}
+		
+		for (RenewableCacheItemOperations<?> rcid : getRenewableCacheService().getCacheItemsOperations()) {
+			// Checking for keys that are in update for too long/ haven't been updated for a long
+			// time.
+			Set<?> keysDuringUpdate = rcid.getKeysDuringUpdate();
+			Map<?, Long> keysUpdates = rcid.getKeysUpdates();
+			// Calculating the effective interval of updates of the cache item.
+			long interval = rcid.getInterval();
+			if (interval == 0) {
+				interval = getRenewableCacheService().getInterval();
+			}
+			
+			for (Object key : keysUpdates.keySet()) {
+				if (now - keysUpdates.get(key) > interval*getUpdateAlertIntervalMultiplier()) {
+					// Issuing an alert.
+					if (keysDuringUpdate.contains(key)) {
+						addAlertForCacheItem(rcid, CacheAlertFactory.createAlertKeyTooLongInUpdate(key));
+					} else {
+						addAlertForCacheItem(rcid, CacheAlertFactory.createAlertKeyNotUpdated(key));
+					}
+				}
+			}
+			
+			// Checking for exceptions.
+			Map<?, Throwable> keysExceptions = rcid.getKeysExceptions();
+			for (Object key : keysExceptions.keySet()) {
+				addAlertForCacheItem(rcid, CacheAlertFactory.createAlertKeyException(key, keysExceptions.get(key)));
+			}
+		}
+	}
+	
+	private synchronized void addAlertForCacheItem(RenewableCacheItemOperations<?> rcid, CacheAlert alert) {
+		Set<CacheAlert> alertsForCacheItem = alertsForCacheItems.get(rcid);
+	
+		if (alertsForCacheItem == null) {
+			alertsForCacheItem = new HashSet<CacheAlert>();
+			alertsForCacheItems.put(rcid, alertsForCacheItem);
+		}
+		
+		if (alertsForCacheItem.add(alert)) {
+			currentNumberOfAlerts++;
+		}
+		
+		cacheItemsWithAlerts.add(rcid);
+	}
+
+	private static Comparator<CacheAlert> cacheAlertComparator = new Comparator<CacheAlert>() {
+		public int compare(CacheAlert ca1, CacheAlert ca2) {
+			if (ca1.getTime() == ca2.getTime()) {
+				return 0;
+			}
+			
+			if (ca1.getTime() < ca2.getTime()) {
+				return 1;
+			}
+			
+			return -1;
+		}
+	};
+	
+	public synchronized List<CacheAlert> getAlertsForCacheItem(RenewableCacheItemOperations<?> rcid) {
+		Set<CacheAlert> alertsForCacheItem = alertsForCacheItems.get(rcid);
+		if (alertsForCacheItem == null) {
+			return null;
+		}
+		
+		// Turning the set into a list and sorting it.
+		List<CacheAlert> alertsList = new ArrayList<CacheAlert>(alertsForCacheItem);
+		Collections.sort(alertsList, cacheAlertComparator);
+		return alertsList;
+	}
+
+	public synchronized Set<RenewableCacheItemOperations<?>> getCacheItemsWithAlerts() {
+		return cacheItemsWithAlerts;
+	}
+
+	public synchronized  void clearAlerts() {
+		currentNumberOfAlerts = 0;
+		
+		cacheItemsWithAlerts.clear();
+		alertsForCacheItems.clear();
+		
+		// Clearing all exceptions in cache items.
+		for (RenewableCacheItemOperations<?> rcid : getRenewableCacheService().getCacheItemsOperations()) {
+			rcid.getKeysExceptions().clear();
+		}
+	}
+}

Modified: labs/shotoku/trunk/shotoku-cache/cache-test/src/java/org/jboss/shotoku/cache/test/TestServlet.java
===================================================================
--- labs/shotoku/trunk/shotoku-cache/cache-test/src/java/org/jboss/shotoku/cache/test/TestServlet.java	2007-08-26 08:11:03 UTC (rev 14573)
+++ labs/shotoku/trunk/shotoku-cache/cache-test/src/java/org/jboss/shotoku/cache/test/TestServlet.java	2007-08-26 09:08:09 UTC (rev 14574)
@@ -13,6 +13,7 @@
 	private TestCacheItem2 tci2;
 	private TestCacheItem tci3;
 	private TestCacheItem2 tci4;
+	private TestCacheItem3 tci5;
 	
 	@Override
 	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
@@ -24,6 +25,7 @@
 		System.out.println(tci3.get("F"));
 		System.out.println(tci4.get("G"));
 		System.out.println(tci4.get("H"));
+		System.out.println(tci5.get("I"));
 	}
 
 	@Override
@@ -32,8 +34,8 @@
 		tci2 = new TestCacheItem2();
 		tci3 = new TestCacheItem();
 		tci4 = new TestCacheItem2();
+		tci5 = new TestCacheItem3();
 		
 		super.init(config);
 	}
-	
 }




More information about the jboss-svn-commits mailing list