Uploaded image for project: 'Jira Data Center'
  1. Jira Data Center
  2. JRASERVER-65246

Plugin caches in Data Center throw ClassNotFoundException on invalidation if custom classes are used as keys

    XMLWordPrintable

Details

    Description

      Summary

      In a JIRA Data Center Environment, during replication of cache defined by plugin, webapp class loader is used to deserialize cache invalidation messages and not OSGi class loader associated with plugin's OSGi bundle. ClassNotFoundException can be seen in the logs.

      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)
      

      Expected Results

      JIRA uses plugin's class loader to deserialize message. No exception is thrown.

      Environment

      • JIRA Data Center

      Workaround (for plugin developers)

      • Use keys that can be serialized/deserialized by webapp class loader (e.g. java.lang.String). (As long as loading cache is used and put() is not called on it, custom classes can be used as cache values).
      • NOT TESTED: Plugin developers may consider wrapping cache creation with a class loader switching code, to ensure that the right class loader is used.
        ClassLoader previous = Thread.currentThread().getContextClassLoader();
        try {
           Thread.currentThread().setContextClassLoader(CustomCacheKey.class.getClassLoader());
           // cache creation code
        } finally {
           Thread.currentThread().setContextClassLoader(previous);
        }
        

        Cache usage does not have to be guarded this way.

      Workaround (for users)

      None.

      Attachments

        Issue Links

          Activity

            People

              cmurat Celebi Murat (Inactive)
              pbugalski Pawel Bugalski (Inactive)
              Votes:
              1 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: