Cache extensions and ClassLoader dependencies

Over the last couple of years, I have done quite a lot of work with modifying and writing Lucee extensions for talking to different caching layers. This leads me to wonder why classes as fundamental as lucee.runtime.cache.tag.udf.UDFCacheItem are buried inside the lucee.lco core, rendering them inaccessible to the default JVM ClassLoader. That means that any cache extension or backend (1) attempting to perform deserialization will fail due to inability to find the class.

The issue was present but avoidable with Lucee 4. With Lucee 5 it is worse because of OSGI. I had to resort to reimplementing java.io.ObjectInputStream to allow passing of a non-standard ClassLoader as an argument during deserialization. Then, I noticed that the Memcached extension is benefiting from the same “fix”, since it was already implemented by the Whalin client library. On the other hand, the MongoDB extension has an open issue concerning support for non-primitive data types, which is presumably also ClassLoader-related.

I could be missing something, but it seems that a lot of issues and extra code could be avoided by a repackaging of critical classes. Any thoughts?

(1) The ability to deserialize objects stored in cache entries is fundamental to the operation of some persistence layers e.g. Apache Ignite.

The reason is to allow to update the Lucee Core without restarting the JVM.

The classes that are “buried” inside the Lucee Core are not part of any API, meaning that they are not designed for public use in general, and their interface could change at any time without notice. You can use them, of course, but any minor update could potentially break your code.

The interfaces in the Lucee Loader are much more stable, and we take into account the fact that external code might use them, so we are much more careful with modifying them.

Thanks for the quick response. That all makes sense, but it’s not as if I went looking through the Lucee class hierarchy and decided that UDFCacheItem was an appropriate class to use. It happens as an automatic consequence of cachePut() or cachedWithin. In other words, I am unable to produce a useful cache extension for Lucee 5 without the modifications to java.io.ObjectInputStream already described.

Perhaps @micstriit will have some ideas for you