I have no idea. Strange. But to make a patch, you have to checkout the code. . . .
--- On Mon, 8/31/09, Tim Cronin <tim.cro...@autonomy.com> wrote: > From: Tim Cronin <tim.cro...@autonomy.com> > Subject: RE: [jira] Commented: (JCS-68) Admin.jsp on remote cache server does > not broadcast removes - patch > To: "JCS Developers List" <jcs-dev@jakarta.apache.org> > Date: Monday, August 31, 2009, 8:22 AM > Any reason that the RemoteCacheServer > class is not exposed in the > Javadocs? > > http://jakarta.apache.org/jcs/apidocs/org/apache/jcs/auxiliary/remote/se > rver/RemoteCacheServerFactory.html > > > -----Original Message----- > From: Aaron Smuts (JIRA) [mailto:j...@apache.org] > Sent: Monday, August 31, 2009 8:29 AM > To: jcs-dev@jakarta.apache.org > Subject: [jira] Commented: (JCS-68) Admin.jsp on remote > cache server > does not broadcast removes - patch > > > [ > https://issues.apache.org/jira/browse/JCS-68?page=com.atlassian.jira.plu > gin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12749487#act > ion_12749487 ] > > Aaron Smuts commented on JCS-68: > -------------------------------- > > Thanks, this is a good idea. Why are you calling the > remove method via > reflection? That's too fragile. Especially > without any unit tests. I > need unit tests for all changes. > > > Admin.jsp on remote cache server does not broadcast > removes - patch > > > ------------------------------------------------------------------- > > > > > Key: JCS-68 > > > URL: https://issues.apache.org/jira/browse/JCS-68 > > > Project: JCS > > Issue Type: Bug > > Components: RMI > Remote Cache > > Affects Versions: jcs-1.3, jcs-1.4-dev > > Environment: > All > > Reporter: > Niall Gallagher > > Assignee: > Aaron Smuts > > Priority: > Minor > > Original Estimate: 0.5h > > Remaining Estimate: 0.5h > > > > We'd like to contribute some patches to fix an issue > with the > JCSAdmin.jsp when it's used on a JCS remote cache server. > > We use this JSP on our remote cache server. This > allows us to browse > the objects stored in our distributed cache (i.e. uploaded > by the client > servers), and allows us to remove arbitrary objects from > the distributed > cache by clicking 'remove' next to the key of the relevant > object > displayed on the JSP. > > The issue is: when we use the unmodified version of > the code to remove > an object, the object is successfully removed from the JCS > remote > server, but the 'remove' event for that object is not > broadcast to all > client machines. Client machines which start up after we > remove the > object get 'null' when they try to retrieve the object (the > desired > behaviour). However client machines which were already > running and using > this object continue to see the object in their view of the > cache. > > This problem occurs because the JCSAdminBean (used by > this JSP) calls > the wrong API in JCS to remove objects from the cache when > it's running > on the remote cache server. It calls the CompositeCache > API, which is > intended for use client-side only. > > Our patches update JCSAdminBean to call this same API > when its running > on a client machine, BUT if it's running on a machine on > which the JCS > remote server is enabled, it calls the RemoteCacheServer > API instead. > > The fix involves replacing 3 methods in > org.apache.jcs.admin.JCSAdminBean as follows: > > /** > > * Clears all regions in the > cache. > > * <p/> > > * If this class is running within > a remote cache server, clears > all regions via the > <code>RemoteCacheServer</code> > > * API, so that removes will be > broadcast to client machines. > Otherwise clears all regions in the cache directly via > > * the usual cache API. > > */ > > public void clearAllRegions() > throws IOException { > > if > (RemoteCacheServerFactory.getRemoteCacheServer() == null) { > > // > Not running in a remote cache server. > > // > Remove objects from the cache directly, as no need to > broadcast removes to client machines... > > > String[] names = > cacheHub.getCacheNames(); > > > for (int i = 0; i < names.length; i++) > { > > > cacheHub.getCache(names[i]).removeAll(); > > } > > } > > else { > > // > Running in a remote cache server. > > // > Remove objects via the RemoteCacheServer API, so that > removes will be broadcast to client machines... > > > try { > > > String[] cacheNames = > CompositeCacheManager.getInstance().getCacheNames(); > > > // Call > remoteCacheServer.removeAll(String) for each > cacheName... > > > // Note: We must do this using reflection > to bypass > its package-private access... > > > Object remoteCacheServerObject = > RemoteCacheServerFactory.getRemoteCacheServer(); > > > Method removeAllMethod = > remoteCacheServerObject.getClass().getMethod("removeAll", > new > Class[]{String.class}); > > > boolean previouslyAccessibility = > removeAllMethod.isAccessible(); > > > removeAllMethod.setAccessible(true); > > > for (int i = 0; i < cacheNames.length; > i++) { > > > String cacheName = cacheNames[i]; > > > > removeAllMethod.invoke(remoteCacheServerObject, > new Object[]{cacheName}); > > > } > > > removeAllMethod.setAccessible(previouslyAccessibility); > > } > > > catch (Exception e) { > > > throw new IllegalStateException("Failed to > remove all > elements from all cache regions: " + e, e); > > } > > } > > } > > /** > > * Clears a particular cache > region. > > * <p/> > > * If this class is running within > a remote cache server, clears > the region via the > <code>RemoteCacheServer</code> > > * API, so that removes will be > broadcast to client machines. > Otherwise clears the region directly via the usual > > * cache API. > > */ > > public void clearRegion(String > cacheName) throws IOException { > > if (cacheName == > null) { > > > throw new IllegalArgumentException("The > cache name > specified was null."); > > } > > if > (RemoteCacheServerFactory.getRemoteCacheServer() == null) { > > // > Not running in a remote cache server. > > // > Remove objects from the cache directly, as no need to > broadcast removes to client machines... > > > cacheHub.getCache(cacheName).removeAll(); > > } > > else { > > // > Running in a remote cache server. > > // > Remove objects via the RemoteCacheServer API, so that > removes will be broadcast to client machines... > > > try { > > > // Call > remoteCacheServer.removeAll(String)... > > > // Note: We must do this using reflection > to bypass > its package-private access... > > > Object remoteCacheServerObject = > RemoteCacheServerFactory.getRemoteCacheServer(); > > > Method removeAllMethod = > remoteCacheServerObject.getClass().getMethod("removeAll", > new > Class[]{String.class}); > > > boolean previouslyAccessibility = > removeAllMethod.isAccessible(); > > > removeAllMethod.setAccessible(true); > > > removeAllMethod.invoke(remoteCacheServerObject, > new > Object[]{cacheName}); > > > removeAllMethod.setAccessible(previouslyAccessibility); > > } > > > catch (Exception e) { > > > throw new IllegalStateException("Failed to > remove all > elements from cache region [" + cacheName + "]: " + e, e); > > } > > } > > } > > /** > > * Removes a particular item from a > particular region. > > * <p/> > > * If this class is running within > a remote cache server, removes > the item via the > <code>RemoteCacheServer</code> > > * API, so that removes will be > broadcast to client machines. > Otherwise clears the region directly via the usual > > * cache API. > > * > > * @param cacheName > > * @param key > > * > > * @throws IOException > > */ > > public void removeItem(String > cacheName, String key) throws > IOException { > > if (cacheName == > null) { > > > throw new IllegalArgumentException("The > cache name > specified was null."); > > } > > if (key == null) > { > > > throw new IllegalArgumentException("The > key specified was > null."); > > } > > if > (RemoteCacheServerFactory.getRemoteCacheServer() == null) { > > // > Not running in a remote cache server. > > // > Remove objects from the cache directly, as no need to > broadcast removes to client machines... > > > cacheHub.getCache(cacheName).remove(key); > > } > > else { > > // > Running in a remote cache server. > > // > Remove objects via the RemoteCacheServer API, so that > removes will be broadcast to client machines... > > > try { > > > Object keyToRemove = null; > > > CompositeCache cache = > CompositeCacheManager.getInstance().getCache(cacheName); > > > // A String key was supplied, but to > remove elements > via the RemoteCacheServer API, we need the > > > // actual key object as stored in the > cache (i.e. a > Serializable object). To find the key in this form, > > > // we iterate through all keys stored in > the memory > cache until we find one whose toString matches > > > // the string supplied... > > > Object[] allKeysInCache = > cache.getMemoryCache().getKeyArray(); > > > for (int i = 0; i < > allKeysInCache.length; i++) { > > > Object keyInCache = > allKeysInCache[i]; > > > if > (keyInCache.toString().equals(key)) { > > > if (keyToRemove == > null) { > > > > keyToRemove = keyInCache; > > > } > > > else { > > > // A > key matching the one specified was > already found... > > > throw > new > IllegalStateException("Unexpectedly found duplicate keys in > the cache > region matching the key specified."); > > > } > > > } > > > } > > > if (keyToRemove == null) { > > > throw new IllegalStateException("No > match for this > key could be found in the set of keys retrieved from the > memory > cache."); > > > } > > > if (!(keyToRemove instanceof > Serializable)) { > > > throw new > IllegalStateException("Found key [" + > keyToRemove + ", " + keyToRemove.getClass() + "] in cache > matching key > specified, however key found in cache is unexpectedly not > serializable."); > > > } > > > // At this point, we have retrieved the > matching > Serializable key. > > > // Call remoteCacheServer.remove(String, > Serializable)... > > > // Note: We must fo this using reflection > to bypass > its package-private access... > > > Object remoteCacheServerObject = > RemoteCacheServerFactory.getRemoteCacheServer(); > > > Method removeMethod = > remoteCacheServerObject.getClass().getMethod("remove", new > Class[]{String.class, Serializable.class}); > > > boolean previouslyAccessibility = > removeMethod.isAccessible(); > > > removeMethod.setAccessible(true); > > > removeMethod.invoke(remoteCacheServerObject, > new > Object[]{cacheName, keyToRemove}); > > > removeMethod.setAccessible(previouslyAccessibility); > > } > > > catch (Exception e) { > > > throw new IllegalStateException("Failed to > remove > element with key [" + key + ", " + key.getClass() + "] from > cache region > [" + cacheName + "]: " + e, e); > > } > > } > > } > > -- > This message is automatically generated by JIRA. > - > You can reply to this email to add a comment to the issue > online. > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: jcs-dev-unsubscr...@jakarta.apache.org > For additional commands, e-mail: jcs-dev-h...@jakarta.apache.org > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: jcs-dev-unsubscr...@jakarta.apache.org > For additional commands, e-mail: jcs-dev-h...@jakarta.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: jcs-dev-unsubscr...@jakarta.apache.org For additional commands, e-mail: jcs-dev-h...@jakarta.apache.org