RE: [jira] Commented: (JCS-68) Admin.jsp on remote cache server does not broadcast removes - patch

Aaron Smuts <[email protected]> Mon, 31 Aug 2009 10:58:03 -0700 (PDT)
Newsgroups gmane.comp.jakarta.turbine.jcs.devel
Message-ID <[email protected]>
I have no idea.  Strange.  =0A=0ABut to make a patch, you have to checkout =
the code.  . . . =0A=0A--- On Mon, 8/31/09, Tim Cronin <Tim.Cronin@autonomy=
.com> wrote:=0A=0A> From: Tim Cronin <[email protected]>=0A> Subject:=
 RE: [jira] Commented: (JCS-68) Admin.jsp on remote cache server does not b=
roadcast removes - patch=0A> To: "JCS Developers List" <[email protected]=
che.org>=0A> Date: Monday, August 31, 2009, 8:22 AM=0A> Any reason that the=
 RemoteCacheServer=0A> class is not exposed in the=0A> Javadocs?=0A> =0A> h=
ttp://jakarta.apache.org/jcs/apidocs/org/apache/jcs/auxiliary/remote/se=0A>=
 rver/RemoteCacheServerFactory.html=0A> =0A> =0A> -----Original Message----=
-=0A> From: Aaron Smuts (JIRA) [mailto:[email protected]] =0A> Sent: Monday, =
August 31, 2009 8:29 AM=0A> To: [email protected]=0A> Subject: [ji=
ra] Commented: (JCS-68) Admin.jsp on remote=0A> cache server=0A> does not b=
roadcast removes - patch=0A> =0A> =0A> =A0 =A0 [=0A> https://issues.apache.=
org/jira/browse/JCS-68?page=3Dcom.atlassian.jira.plu=0A> gin.system.issueta=
bpanels:comment-tabpanel&focusedCommentId=3D12749487#act=0A> ion_12749487 ]=
 =0A> =0A> Aaron Smuts commented on JCS-68:=0A> ---------------------------=
-----=0A> =0A> Thanks, this is a good idea.=A0 Why are you calling the=0A> =
remove method via=0A> reflection?=A0 That's too fragile.=A0 Especially=0A> =
without any unit tests.=A0 I=0A> need unit tests for all changes.=A0 =0A> =
=0A> > Admin.jsp on remote cache server does not broadcast=0A> removes - pa=
tch=0A> >=0A> -------------------------------------------------------------=
------=0A> >=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Key: JCS-68=0A> =
>=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0URL: https://issues.apache.org/ji=
ra/browse/JCS-68=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Project: JCS=0A> >=
=A0 =A0 =A0 =A0 =A0 Issue Type: Bug=0A> >=A0 =A0 =A0 =A0 =A0 Components: RM=
I=0A> Remote Cache=0A> >=A0 =A0 Affects Versions: jcs-1.3, jcs-1.4-dev=0A> =
>=A0 =A0 =A0 =A0=A0=A0Environment:=0A> All=0A> >=A0 =A0 =A0 =A0 =A0 =A0 Rep=
orter:=0A> Niall Gallagher=0A> >=A0 =A0 =A0 =A0 =A0 =A0 Assignee:=0A> Aaron=
 Smuts=0A> >=A0 =A0 =A0 =A0 =A0 =A0 Priority:=0A> Minor=0A> >=A0=A0=A0Origi=
nal Estimate: 0.5h=0A> >=A0 Remaining Estimate: 0.5h=0A> >=0A> > We'd like =
to contribute some patches to fix an issue=0A> with the=0A> JCSAdmin.jsp wh=
en it's used on a JCS remote cache server.=0A> > We use this JSP on our rem=
ote cache server. This=0A> allows us to browse=0A> the objects stored in ou=
r distributed cache (i.e. uploaded=0A> by the client=0A> servers), and allo=
ws us to remove arbitrary objects from=0A> the distributed=0A> cache by cli=
cking 'remove' next to the key of the relevant=0A> object=0A> displayed on =
the JSP.=0A> > The issue is: when we use the unmodified version of=0A> the =
code to remove=0A> an object, the object is successfully removed from the J=
CS=0A> remote=0A> server, but the 'remove' event for that object is not=0A>=
 broadcast to all=0A> client machines. Client machines which start up after=
 we=0A> remove the=0A> object get 'null' when they try to retrieve the obje=
ct (the=0A> desired=0A> behaviour). However client machines which were alre=
ady=0A> running and using=0A> this object continue to see the object in the=
ir view of the=0A> cache.=0A> > This problem occurs because the JCSAdminBea=
n (used by=0A> this JSP) calls=0A> the wrong API in JCS to remove objects f=
rom the cache when=0A> it's running=0A> on the remote cache server. It call=
s the CompositeCache=0A> API, which is=0A> intended for use client-side onl=
y.=0A> > Our patches update JCSAdminBean to call this same API=0A> when its=
 running=0A> on a client machine, BUT if it's running on a machine on=0A> w=
hich the JCS=0A> remote server is enabled, it calls the RemoteCacheServer=
=0A> API instead.=0A> > The fix involves replacing 3 methods in=0A> org.apa=
che.jcs.admin.JCSAdminBean as follows:=0A> >=A0 =A0=A0=A0/**=0A> >=A0 =A0 =
=A0 * Clears all regions in the=0A> cache.=0A> >=A0 =A0 =A0 * <p/>=0A> >=A0=
 =A0 =A0 * If this class is running within=0A> a remote cache server, clear=
s=0A> all regions via the=0A> <code>RemoteCacheServer</code>=0A> >=A0 =A0 =
=A0 * API, so that removes will be=0A> broadcast to client machines.=0A> Ot=
herwise clears all regions in the cache directly via=0A> >=A0 =A0 =A0 * the=
 usual cache API.=0A> >=A0 =A0 =A0 */=0A> >=A0 =A0=A0=A0public void clearAl=
lRegions()=0A> throws IOException {=0A> >=A0 =A0 =A0 =A0=A0=A0if=0A> (Remot=
eCacheServerFactory.getRemoteCacheServer() =3D=3D null) {=0A> >=A0 =A0 =A0 =
=A0 =A0 =A0=A0=A0//=0A> Not running in a remote cache server.=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0=A0=A0//=0A> Remove objects from the cache directly, as no n=
eed to=0A> broadcast removes to client machines...=0A> >=A0 =A0 =A0 =A0 =A0=
=0A> =A0=A0=A0String[] names =3D=0A> cacheHub.getCacheNames();=0A> >=A0 =A0=
 =A0 =A0 =A0=0A> =A0=A0=A0for (int i =3D 0; i < names.length; i++)=0A> {=0A=
> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0cacheHub.getCache(names[i]).rem=
oveAll();=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0}=
=0A> >=A0 =A0 =A0 =A0=A0=A0else {=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> =
Running in a remote cache server.=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> =
Remove objects via the RemoteCacheServer API, so that=0A> removes will be b=
roadcast to client machines...=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0try {=
=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0String[] cacheNames =3D=0A> =
CompositeCacheManager.getInstance().getCacheNames();=0A> >=A0 =A0 =A0 =A0 =
=A0 =A0 =A0=0A> =A0=A0=A0// Call=0A> remoteCacheServer.removeAll(String) fo=
r each=0A> cacheName...=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// No=
te: We must do this using reflection=0A> to bypass=0A> its package-private =
access...=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Object remoteCacheS=
erverObject =3D=0A> RemoteCacheServerFactory.getRemoteCacheServer();=0A> >=
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Method removeAllMethod =3D=0A> rem=
oteCacheServerObject.getClass().getMethod("removeAll",=0A> new=0A> Class[]{=
String.class});=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0boolean previ=
ouslyAccessibility =3D=0A> removeAllMethod.isAccessible();=0A> >=A0 =A0 =A0=
 =A0 =A0 =A0 =A0=0A> =A0=A0=A0removeAllMethod.setAccessible(true);=0A> >=A0=
 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0for (int i =3D 0; i < cacheNames.leng=
th;=0A> i++) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0=A0=A0String=
 cacheName =3D cacheNames[i];=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=
=0A> =A0=A0=A0removeAllMethod.invoke(remoteCacheServerObject,=0A> new Objec=
t[]{cacheName});=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0}=0A> >=0A> =
removeAllMethod.setAccessible(previouslyAccessibility);=0A> >=A0 =A0 =A0 =
=A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0catch (Exception e=
) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0throw new IllegalStateExc=
eption("Failed to=0A> remove all=0A> elements from all cache regions: " + e=
, e);=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=
=A0 =A0=A0=A0}=0A> >=A0 =A0=A0=A0/**=0A> >=A0 =A0 =A0 * Clears a particular=
 cache=0A> region.=0A> >=A0 =A0 =A0 * <p/>=0A> >=A0 =A0 =A0 * If this class=
 is running within=0A> a remote cache server, clears=0A> the region via the=
=0A> <code>RemoteCacheServer</code>=0A> >=A0 =A0 =A0 * API, so that removes=
 will be=0A> broadcast to client machines.=0A> Otherwise clears the region =
directly via the usual=0A> >=A0 =A0 =A0 * cache API.=0A> >=A0 =A0 =A0 */=0A=
> >=A0 =A0=A0=A0public void clearRegion(String=0A> cacheName) throws IOExce=
ption {=0A> >=A0 =A0 =A0 =A0=A0=A0if (cacheName =3D=3D=0A> null) {=0A> >=A0=
 =A0 =A0 =A0 =A0=0A> =A0=A0=A0throw new IllegalArgumentException("The=0A> c=
ache name=0A> specified was null.");=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =
=A0 =A0 =A0=A0=A0if=0A> (RemoteCacheServerFactory.getRemoteCacheServer() =
=3D=3D null) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> Not running in a re=
mote cache server.=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> Remove objects =
from the cache directly, as no need to=0A> broadcast removes to client mach=
ines...=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0cacheHub.getCache(cacheName).=
removeAll();=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0else {=
=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> Running in a remote cache server.=
=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=0A> Remove objects via the RemoteCach=
eServer API, so that=0A> removes will be broadcast to client machines...=0A=
> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0try {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=
=0A> =A0=A0=A0// Call=0A> remoteCacheServer.removeAll(String)...=0A> >=A0 =
=A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// Note: We must do this using reflect=
ion=0A> to bypass=0A> its package-private access...=0A> >=A0 =A0 =A0 =A0 =
=A0 =A0 =A0=0A> =A0=A0=A0Object remoteCacheServerObject =3D=0A> RemoteCache=
ServerFactory.getRemoteCacheServer();=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =
=A0=A0=A0Method removeAllMethod =3D=0A> remoteCacheServerObject.getClass().=
getMethod("removeAll",=0A> new=0A> Class[]{String.class});=0A> >=A0 =A0 =A0=
 =A0 =A0 =A0 =A0=0A> =A0=A0=A0boolean previouslyAccessibility =3D=0A> remov=
eAllMethod.isAccessible();=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0re=
moveAllMethod.setAccessible(true);=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=
=A0=A0removeAllMethod.invoke(remoteCacheServerObject,=0A> new=0A> Object[]{=
cacheName});=0A> >=0A> removeAllMethod.setAccessible(previouslyAccessibilit=
y);=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=
=A0catch (Exception e) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0thro=
w new IllegalStateException("Failed to=0A> remove all=0A> elements from cac=
he region [" + cacheName + "]: " + e, e);=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=
=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0=A0=A0}=0A> >=A0 =A0=A0=A0/**=
=0A> >=A0 =A0 =A0 * Removes a particular item from a=0A> particular region.=
=0A> >=A0 =A0 =A0 * <p/>=0A> >=A0 =A0 =A0 * If this class is running within=
=0A> a remote cache server, removes=0A> the item via the=0A> <code>RemoteCa=
cheServer</code>=0A> >=A0 =A0 =A0 * API, so that removes will be=0A> broadc=
ast to client machines.=0A> Otherwise clears the region directly via the us=
ual=0A> >=A0 =A0 =A0 * cache API.=0A> >=A0 =A0 =A0 *=0A> >=A0 =A0 =A0 * @pa=
ram cacheName=0A> >=A0 =A0 =A0 * @param key=0A> >=A0 =A0 =A0 *=0A> >=A0 =A0=
 =A0 * @throws IOException=0A> >=A0 =A0 =A0 */=0A> >=A0 =A0=A0=A0public voi=
d removeItem(String=0A> cacheName, String key) throws=0A> IOException {=0A>=
 >=A0 =A0 =A0 =A0=A0=A0if (cacheName =3D=3D=0A> null) {=0A> >=A0 =A0 =A0 =
=A0 =A0=0A> =A0=A0=A0throw new IllegalArgumentException("The=0A> cache name=
=0A> specified was null.");=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =
=A0=A0=A0if (key =3D=3D null)=0A> {=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0t=
hrow new IllegalArgumentException("The=0A> key specified was=0A> null.");=
=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0if=0A> (RemoteCacheS=
erverFactory.getRemoteCacheServer() =3D=3D null) {=0A> >=A0 =A0 =A0 =A0 =A0=
 =A0=A0=A0//=0A> Not running in a remote cache server.=0A> >=A0 =A0 =A0 =A0=
 =A0 =A0=A0=A0//=0A> Remove objects from the cache directly, as no need to=
=0A> broadcast removes to client machines...=0A> >=A0 =A0 =A0 =A0 =A0=0A> =
=A0=A0=A0cacheHub.getCache(cacheName).remove(key);=0A> >=A0 =A0 =A0 =A0=A0=
=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0else {=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=
=0A> Running in a remote cache server.=0A> >=A0 =A0 =A0 =A0 =A0 =A0=A0=A0//=
=0A> Remove objects via the RemoteCacheServer API, so that=0A> removes will=
 be broadcast to client machines...=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0t=
ry {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Object keyToRemove =3D n=
ull;=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0CompositeCache cache =3D=
=0A> CompositeCacheManager.getInstance().getCache(cacheName);=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// A String key was supplied, but to=0A> r=
emove elements=0A> via the RemoteCacheServer API, we need the=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// actual key object as stored in the=0A> =
cache (i.e. a=0A> Serializable object). To find the key in this form,=0A> >=
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// we iterate through all keys sto=
red in=0A> the memory=0A> cache until we find one whose toString matches=0A=
> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// the string supplied...=0A> >=
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0Object[] allKeysInCache =3D=0A> ca=
che.getMemoryCache().getKeyArray();=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =
=A0=A0=A0for (int i =3D 0; i <=0A> allKeysInCache.length; i++) {=0A> >=A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0=A0=A0Object keyInCache =3D=0A> allK=
eysInCache[i];=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0=A0=A0if=0A>=
 (keyInCache.toString().equals(key)) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=0A> =A0 =A0 =A0 =A0=A0=A0if (keyToRemove =3D=3D=0A> null) {=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0keyToRemove =
=3D keyInCache;=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0 =A0 =A0=A0=
=A0}=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0 =A0 =A0=A0=A0else {=
=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0 =A0 =A0 =A0 =A0=A0=A0// A=
=0A> key matching the one specified was=0A> already found...=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0 =A0 =A0 =A0 =A0=A0=A0throw=0A> new=0A> =
IllegalStateException("Unexpectedly found duplicate keys in=0A> the cache=
=0A> region matching the key specified.");=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0=0A> =A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =
=A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0}=0A> >=A0 =A0=
 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0if (keyToRemove =3D=3D null) {=0A> >=A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0 =A0=A0=A0throw new IllegalStateExceptio=
n("No=0A> match for this=0A> key could be found in the set of keys retrieve=
d from the=0A> memory=0A> cache.");=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =
=A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0if (!(keyToRemove =
instanceof=0A> Serializable)) {=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =
=A0 =A0=A0=A0throw new=0A> IllegalStateException("Found key [" +=0A> keyToR=
emove + ", " + keyToRemove.getClass() + "] in cache=0A> matching key=0A> sp=
ecified, however key found in cache is unexpectedly not=0A> serializable.")=
;=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0 =
=A0 =A0=0A> =A0=A0=A0// At this point, we have retrieved the=0A> matching=
=0A> Serializable key.=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0// Cal=
l remoteCacheServer.remove(String,=0A> Serializable)...=0A> >=A0 =A0 =A0 =
=A0 =A0 =A0 =A0=0A> =A0=A0=A0// Note: We must fo this using reflection=0A> =
to bypass=0A> its package-private access...=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =
=A0=0A> =A0=A0=A0Object remoteCacheServerObject =3D=0A> RemoteCacheServerFa=
ctory.getRemoteCacheServer();=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=
=A0Method removeMethod =3D=0A> remoteCacheServerObject.getClass().getMethod=
("remove", new=0A> Class[]{String.class, Serializable.class});=0A> >=A0 =A0=
 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0boolean previouslyAccessibility =3D=0A> r=
emoveMethod.isAccessible();=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0r=
emoveMethod.setAccessible(true);=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=
=A0=A0removeMethod.invoke(remoteCacheServerObject,=0A> new=0A> Object[]{cac=
heName, keyToRemove});=0A> >=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0remove=
Method.setAccessible(previouslyAccessibility);=0A> >=A0 =A0 =A0 =A0 =A0 =A0=
=A0=A0}=0A> >=A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0catch (Exception e) {=0A> >=
=A0 =A0 =A0 =A0 =A0 =A0 =A0=0A> =A0=A0=A0throw new IllegalStateException("F=
ailed to=0A> remove=0A> element with key [" + key + ", " + key.getClass() +=
 "] from=0A> cache region=0A> [" + cacheName + "]: " + e, e);=0A> >=A0 =A0 =
=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0 =A0 =A0=A0=A0}=0A> >=A0 =A0=A0=A0}=0A> =
=0A> -- =0A> This message is automatically generated by JIRA.=0A> -=0A> You=
 can reply to this email to add a comment to the issue=0A> online.=0A> =0A>=
 =0A> ---------------------------------------------------------------------=
=0A> To unsubscribe, e-mail: [email protected]=0A> For=
 additional commands, e-mail: [email protected]=0A> =0A> =0A>=
 ---------------------------------------------------------------------=0A> =
To unsubscribe, e-mail: [email protected]=0A> For addi=
tional commands, e-mail: [email protected]=0A> =0A>