I’m trying to use cache in JIRA Data Center but I’m getting this error:
java.lang.ClassCastException: com.softwareplant.util.lang.POJO cannot be cast to com.softwareplant.util.lang.POJO
at com.softwareplant.datacenter.DataCenterService.getAllJIRAS(DataCenterService.java:67)
This error occurs when I’m iterating through values in my cache:
It is good to mention that we ended up with “no security manager: RMI class loader disabled” if a class was not added to the application classpath.
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: com.softwareplant.util.lang.POJO (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:355)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:162)
at net.sf.ehcache.distribution.RMICachePeer_Stub.remove(Unknown Source)
at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.replicateRemovalNotification(RMISynchronousCacheReplicator.java:243)
at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.notifyElementRemoved(RMISynchronousCacheReplicator.java:229)
at net.sf.ehcache.event.RegisteredEventListeners.internalNotifyElementRemoved(RegisteredEventListeners.java:144)
at net.sf.ehcache.event.RegisteredEventListeners.notifyElementRemoved(RegisteredEventListeners.java:124)
at net.sf.ehcache.Cache.notifyRemoveInternalListeners(Cache.java:2322)
at net.sf.ehcache.Cache.removeInternal(Cache.java:2305)
at net.sf.ehcache.Cache.remove(Cache.java:2207)
at net.sf.ehcache.Cache.remove(Cache.java:2125)
at net.sf.ehcache.constructs.EhcacheDecoratorAdapter.remove(EhcacheDecoratorAdapter.java:154)
at com.atlassian.cache.ehcache.LoadingCache.remove(LoadingCache.java:208)
at com.atlassian.cache.ehcache.DelegatingCache.remove(DelegatingCache.java:134)
In our experience, relying on Java object serialization may lead to a plethora of problems. You may want to consider serializing to some alternative format, like JSON.
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: com.softwareplant.util.lang.POJO (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:355)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
is caused by the fact during cache replication in Data Center RMI uses webapp class loader to deserialize cache invalidation message and not OSGi class loader associated with your plugin’s OSGi bundle.
The easiest way to work around this problem is to use keys that can be serialized/deserialized by webapp class loader (e.g. java.lang.String). (As long as you use loading cache and do not call put() on it you should be fine with using your own classes as cache values).
The Atlassian guide on using Data Centre Compatible caches here says the cache can contain keys and values that implement Serializable however from what I have seen serializing pojos does not work as there are different classloaders in play which results in ClassCastException.
I side stepped this problem by having local caches on each node but using a single key value pair in the Atlassian Data Centre Cache to ensure local caches were up to date. I stored the Java epoch time in the Data Centre cache. Each node checks this, if it is the same as its local copy its local cache is safe to use. If its changed the local cache is destroyed and rebuilt with the local epoch time being updated.