Details
-
Bug
-
Status: Resolved
-
Critical
-
Resolution: Fixed
-
jcs-3.2
-
None
Description
After setting up remote RMI cache, with the central cache service running in the same app server/JVM (JDK version 11) as ~4 clients, there were intermittent put and remove failures, as well as issues similar to JCS-237, JCS-238, and JCS-239.
While investigating the intermittent put/remove issues, the remote server log showed the following-
Error while running event from Queue: PutEvent for key: key1 value: null. Retrying... java.rmi.RemoteException: Method is not Remote: interface org.apache.commons.jcs3.engine.behavior.ICacheListener::public abstract void org.apache.commons.jcs3.engine.behavior.ICacheListener.handlePut(org.apache.commons.jcs3.engine.behavior.ICacheElement) throws java.io.IOException at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:214) ~[?:?] at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:162) ~[?:?] at com.sun.proxy.$Proxy2195.handlePut(Unknown Source) ~[?:?] at org.apache.commons.jcs3.engine.AbstractCacheEventQueue$PutEvent.doRun(AbstractCacheEventQueue.java:277) ~[commons-jcs3-core-3.2.jar:3.2] at org.apache.commons.jcs3.engine.AbstractCacheEventQueue$AbstractCacheEvent.run(AbstractCacheEventQueue.java:216) ~[commons-jcs3-core-3.2.jar:3.2] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?] at java.lang.Thread.run(Thread.java:829) ~[?:?]
This pointed to an incorrect listener being registered from the client(s), but when debugging, I saw that the clients were registering the correct listener type, which implements the Remote interface-
listener = RemoteCacheListener: AbstractRemoteCacheListener: RemoteHost = localhost:1101 ListenerId = 4
I understand there's a class hierarchy in place where the RemoveCacheListener implements the IRemoteCacheListener interface, which is a sub-interface of Remote, but therein lies the issue. When the event queue is being processed at runtime and the ICacheListener is being proxied to the appropriate concrete class, the JVM does not recognize the sub-interface and thus, the Remote interface is not seen. The appears to occur in JDK 11 JVMs but not JDK 8. In other words, JCS 3.2 remote cache does not appear to work properly in JDK 11 (and higher?) runtimes.
I "resolved" this by implementing the Remote interface in the ICacheListener, and this actually resolved JCS-237, JCS-238, and JCS-239. That said, it's likely not the optimal solution here. Another option-
Create another abstract class, AbstractRemoteCacheEventQueue, that passes the IRemoteCacheListener rather than the base ICacheListener to the applicable listener. This would obviously have to be added into the appropriate place(s) in the hierarchy (i.e., RemoteCacheListener, etc.).