Hi! We're experiencing a problem when trying to initialize Velocity from our webapp deployed to TomEE embedded version 8.0.15. The error we're getting is:
failed to access class org.apache.velocity.runtime.resource.ResourceCacheImpl$LRUMap from class org.apache.velocity.runtime.resource.ResourceCacheImpl (org.apache.velocity.runtime.resource.ResourceCacheImpl$LRUMap is in unnamed module of loader 'app'; org.apache.velocity.runtime.resource.ResourceCacheImpl is in unnamed module of loader org.apache.openejb.util.classloader.URLClassLoaderFirst @4dcbae55 We have debugged and tried to understand the issue and this is our findings: When Velocity is initialized (using the Velocity.init(props)), Velocity loads the class ResourceCacheImpl by using the classloader from the current thread (Thread.currentThread().getContextClassLoader()). When loading Velocity the context class loader on the current thread is TomEEWebappClassLoader. This class loader delegates to the URLClassLoaderFirst <https://github.com/apache/tomee/blob/main/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomEEWebappClassLoader.java#L201> and the result is that ResourceCacheImpl is loaded and the class loader for that class is URLClassLoaderFirst. After the class is loaded, Velocity calls the ResourceCacheImpl.initialize(..) method. This method tries to instantiate the inner class ResourceCacheImpl$LRUMap using "new LRUMap"the. Since this class is not loaded yet, the JVM tries to load it using the URLClassLoaderFirst.loadClass method. The problem is that this class loader delegates to the system class loader here <https://github.com/apache/tomee/blob/main/container/openejb-core/src/main/java/org/apache/openejb/util/classloader/URLClassLoaderFirst.java#L119> and the ResourceCacheImpl$LRUMap is then loaded from the system class loader (AppClassLoader). The result is then that the two classes are loaded from different class loaders, and the exception mentioned in the beginning is thrown. We have tried to fix this by using the properties openejb.classloader.forced-skip and openejb.classloader.forced-load. The forced-skip property seems to work, but I guess we are then loading the classes from the velocity artifact that TomEE uses, and not the Velocity artifact from our webapp? This is not optimal as we would like to be able to control and use our own version of velocity, no matter which version TomEE Embedded uses. The forced-load option does not seem to have any effect. To me it looks like the reason is that the URLClassLoaderFirst delegates to the system class loader *before* it checks the forced-load property, but there might be things here that I don't see. Do you have any idea on how to fix this issue? And in particular if you think the issue is in our webapp, velocity or in TomEE itself? Any thoughts or input would be highly appreciated! Regards, Henrik Wingerei