CreateDynamicProxy errors when proxying javax.servlet.*

I’m using createDynamicProxy to wrap javax.servlet.Filter & javax.servlet.FilterChain in order to run a custom request filtering pipeline.

var javaFilterChain = createDynamicProxy(this, ["javax.servlet.FilterChain"]);

This works in 5.3, but in 5.4, it fails with

NoSuchMethodException V74060b24f0ec0385d9f86f0aa69578ed4150.<init>(lucee.runtime.config.ConfigWeb, lucee.runtime.Component)

However, looking at the decompiled class file for V74060b24f0ec0385d9f86f0aa69578ed4150:

// Source code is decompiled from a .class file using FernFlower decompiler.
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import lucee.loader.engine.CFMLEngineFactory;
import lucee.runtime.Component;
import lucee.runtime.config.ConfigWeb;
import lucee.runtime.util.JavaProxyUtil;

public class V74060b24f0ec0385d9f86f0aa69578ed4150 implements FilterChain {
   private Component cfc;
   private ConfigWeb config;

   public V74060b24f0ec0385d9f86f0aa69578ed4150(ConfigWeb config, Component cfc) {
      this.config = config;
      this.cfc = cfc;
   }

   public final void doFilter(ServletRequest var1, ServletResponse var2) {
      ((JavaProxyUtil)CFMLEngineFactory.getInstance().getJavaProxyUtil()).call(this.config, this.cfc, "doFilter", new Object[]{((JavaProxyUtil)CFMLEngineFactory.getInstance().getJavaProxyUtil()).toCFML(var1), ((JavaProxyUtil)CFMLEngineFactory.getInstance().getJavaProxyUtil()).toCFML(var2)});
   }
}

Clearly in the bytecode the constructor exists - is this some classloader weirdness going on?

Don’t forget to tell us about your stack!

OS: Linux
Java Version: 11
Tomcat Version: 8 or 9
Lucee Version: 5.4.4

Example

createDynamicProxy("lucee.Component", ["javax.servlet.FilterChain"]);

Stacktrace:

lucee.runtime.exp.NativeException: V74060b24f0ec0385d9f86f0aa69578ed4150.<init>(lucee.runtime.config.ConfigWeb, lucee.runtime.Component)
  at java.lang.Class.getConstructor0(Class.java:3082)
  at java.lang.Class.getConstructor(Class.java:1825)
  at lucee.transformer.bytecode.util.JavaProxyFactory.newInstance(JavaProxyFactory.java:381)
  at lucee.transformer.bytecode.util.JavaProxyFactory.createProxy(JavaProxyFactory.java:216)
  at lucee.runtime.functions.other.CreateDynamicProxy._call(CreateDynamicProxy.java:102)
  at lucee.runtime.functions.other.CreateDynamicProxy.call(CreateDynamicProxy.java:51)
  at fctest_cfc$cf.udfCall(/fctest.cfc:3)
  at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112)
  at lucee.runtime.type.UDFImpl._call(UDFImpl.java:358)
  at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223)
  at lucee.runtime.ComponentImpl._call(ComponentImpl.java:698)
  at lucee.runtime.ComponentImpl._call(ComponentImpl.java:586)
  at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1933)
  at lucee.runtime.functions.other._CreateComponent.call(_CreateComponent.java:66)
  at application_cfc$cf.initComponent(/Application.cfc:8)
  at application_cfc$cf.newInstance(/Application.cfc:7)
  at lucee.runtime.component.ComponentLoader.initComponent(ComponentLoader.java:632)
  at lucee.runtime.component.ComponentLoader._loadComponent(ComponentLoader.java:571)
  at lucee.runtime.component.ComponentLoader.loadComponent(ComponentLoader.java:448)
  at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:116)
  at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:44)
  at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2493)
  at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2478)
  at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2449)
  at lucee.runtime.engine.Request.exe(Request.java:45)
  at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1215)
  at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1161)
  at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
  at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
  at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
  at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1686)
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  at org.apache.tomcat.util.net.AbstractEndpoint.processSocket(AbstractEndpoint.java:1104)
  at org.apache.tomcat.util.net.Nio2Endpoint.setSocketOptions(Nio2Endpoint.java:336)
  at org.apache.tomcat.util.net.Nio2Endpoint$Nio2Acceptor.completed(Nio2Endpoint.java:437)
  at org.apache.tomcat.util.net.Nio2Endpoint$Nio2Acceptor.completed(Nio2Endpoint.java:392)
  at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
  at sun.nio.ch.Invoker$2.run(Invoker.java:218)
  at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  at java.lang.Thread.run(Thread.java:750)
 Caused by: java.lang.NoSuchMethodException: V74060b24f0ec0385d9f86f0aa69578ed4150.<init>(lucee.runtime.config.ConfigWeb, lucee.runtime.Component)

It seems, as a workaround, I can create an interface that extends javax.servlet.Filter*, and create a dynamic proxy from that, so it does appear to be a problem with the classloader hierarchy:

package org.jdsnet.servlet;

public interface FilterChain extends javax.servlet.FilterChain {}
createDynamicProxy("lucee.Component", "org.jdsnet.servlet.FilterChain");