Running a thread inside a thread in Lucee 4


#1

I had the need to run a cfthread from inside another cfthread in Lucee recently. @micstriit mentioned that this was already possible in Lucee 5.1, however my project was using Lucee 4.5 and unable to upgrade at the moment.

It is fairly easy to fire off a Java thread by creating a CFC with a “void run()” method and using createDynamicProxy() to create it as an instance of “java.lang.Runnable”. Then it can be passed into a java.lang.Thread() constructor and started with “start()”. This works well, but the thread runs outside of the page context and doesn’t get access to settings like CF mappings and the “thread” scope which makes it difficult to use.

In a Slack conversation with Micha he said,

when you create a new thread and you wanna run CFML code in that thread, you need to create a PageContext for that thread and register that PageContext with that thread and you also need to register the ConfigWeb object with that thread.

I don’t know what it takes “register” a package context or a configWeb object with a thread, so I’m creating this post here so he can hopefully explain that and the answer will be documented for others.


#2

Are you sure this works? I tried it and I get:

ce 	lucee.runtime.exp.NativeException: class java.lang.Runnable is invalid or doesn't exist
 	at lucee.commons.lang.PhysicalClassLoader.findClass(PhysicalClassLoader.java:146)
 	at lucee.commons.lang.PhysicalClassLoader.loadClass(PhysicalClassLoader.java:127)
 	at lucee.commons.lang.PhysicalClassLoader.loadClass(PhysicalClassLoader.java:107)
 	at java.lang.ClassLoader.defineClass1(Native Method)
 	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
 	at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
 	at lucee.commons.lang.PhysicalClassLoader._loadClass(PhysicalClassLoader.java:163)
 	at lucee.commons.lang.PhysicalClassLoader.loadClass(PhysicalClassLoader.java:158)
 	at lucee.transformer.bytecode.util.JavaProxyFactory.createProxy(JavaProxyFactory.java:311)
 	at lucee.runtime.functions.other.CreateDynamicProxy._call(CreateDynamicProxy.java:95)
 	at lucee.runtime.functions.other.CreateDynamicProxy.call(CreateDynamicProxy.java:44)
 	at java_executor_test_cfm855$cf.call(/java-executor-test.cfm:8)
 	at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:904)
 	at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:819)
 	at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:814)
 	at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:805)
 	at application_cfc$cf.udfCall(/Application.cfc:6)
 	at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:105)
 	at lucee.runtime.type.UDFImpl._call(UDFImpl.java:337)
 	at lucee.runtime.type.UDFImpl.call(UDFImpl.java:224)
 	at lucee.runtime.ComponentImpl._call(ComponentImpl.java:697)
 	at lucee.runtime.ComponentImpl._call(ComponentImpl.java:580)
 	at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1903)
 	at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:422)
 	at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:224)
 	at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:43)
 	at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2265)
 	at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2257)
 	at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2225)
 	at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:881)
 	at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:102)
 	at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:62)
 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
 	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
 	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
 	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
 	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
 	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
 	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 	at java.lang.Thread.run(Thread.java:745)

#3

Hi @kliakos sorry for the lack of example in my first post. Here is the code to try this out on your own.

Create a component called myRunnable.cfc with the following code

component {
	
	function run() {
		systemOutput( 'Starting thread.', true );
		sleep( 2000 );
		systemOutput( 'Stopping thread.', true );
	}
	
}

Then run this code from another file:

myRunnable = createDynamicProxy( new myRunnable(), 'java.lang.Runnable' );
myThread = createObject( 'java', 'java.lang.Thread' ).init( myRunnable );
myThread.start();

You’ll see this in your console log:

Starting thread.
Stopping thread.

#4

Do you have this.javaSettings in your Application.cfc?

I figured out my problem was this ( actually the lack of it ). Found the solution from here


#5

Nope, no javasettings defined in my Application.cfc. What version of Lucee are you running this on? I’m on 4.5


#6

I am on 5.1