Issues with CFCProxy & PageContext when used with Quartz Scheduler

I’m working on porting over some code from ACF10 to Lucee 5. The code I’m working on uses the Quartz Scheduler library that ships with ACF10 (which is Quartz v2.1.0) to build a task scheduling system that’s used by application to schedule tasks within the application. This code uses the Quartz Scheduler APIs directly and does not us the functionality. The code works by registering a generic listener/job handler (in Java) which then acts as a bridge to ColdFusion by using CFCProxy to call various CFC which actually implement the business logic for the task that’s scheduled.

This has all has been working fine for us.

However, in porting the code over to Lucee I’ve run into an issue I’m having trouble figuring out how to resolve.

In Quartz, the when a job is triggered, it runs inside the JVM where the CFML engine is running, but not run within the context of the application.

So, when my Java code invokes an instance of CFCProxy and then tries to call the invoke() method, the PageContext is null, which prevents the CFCProxy.initCFC() private member from being able to create an instance of the CFC.

NOTE — There appear to be some actual bugs in CFCProxy. I’ve had to fork the code to get it working correctly. I plan to open up a Jira issue regarding these bugs later.

Anyway, I’ve found that before initializing my instance of CFCProxy, I can run the following code to try and build a PageContext if it’s not found:

lucee.loader.engine.CFMLEngine engine = lucee.loader.engine.CFMLEngineFactory.getInstance();
lucee.runtime.PageContext pc = engine.getThreadPageContext();

// we're running outside of the Lucee ennvironment, so we need to register a page context
if( pc == null ){
	pc = engine.createPageContext(new java.io.File("."), "localhost", "/", null, null, null, null, null, null, -1, true);
}

The problem is when I do this, the PageContext does not appear to have access to the Application mappings. The component that’s being called extends another CFC using a mapping defined in the Application.cfc. When the CFCProxy.initCFC() code runs, it ends up throwing the following error:

“invalid interface definition, can’t find interface [mapped.path.ITaskEventHandler]”

If I change the CFC to use a mapped path at the server level, it works. However, I’m having other issues which leads me to think my PageContext is not quite right.

Is there a way I can get to the correct PageContext I’m after?

Instead of using engine.createPageContext(), should I be doing something like this instead:

engine.createConfig(new java.io.File("."), "localhost");

HttpServletRequest req = null;
// headers for this simulated request
Map<String, Object> headers = new HashMap<String, Object>();
// parameters for this simulated request
Map<String, String> parameters = new HashMap<String, String>();

// the header/parameters cannot be null
req = creator.createHttpServletRequest(new File("."), "Lucee", "/", "", null, headers, parameters, null, null);
HttpServletResponse rsp = creator.createHttpServletResponse(out);

final PageContext pc = creator.createPageContext(req, rsp, DevNullOutputStream.DEV_NULL_OUTPUT_STREAM);

Any help would be greatly appreciated.

did you see?

Zak,

Thanks. I have read that. However, it has the same core issue. The problem is with this:

PageContext pc = engine.getThreadPageContext();

You need a PageContext object, which is my core issue. I’m just trying to find the correct way to get the PageContext for the application I want to target.

Perhaps my issue is with the file path and I need to specify a path to the application. Not sure. I can’t find any better documentation and I’m having trouble getting a mental model from the source code.

Hi Zak,

i think i have a very similiar problem.
my application.cfc defines an application[“path”] variable. This variable is used by a cfc which is created by a Java-Thread. This java-Thread was created and started by a Java class. This java class is called from the index.cfm.

If i use the pageContext retrieved from getThreadPageContext everything works as expected:

The application variable is resolved and the cfcs can be loaded. but not in the Thread. In that case i get the message that there is no such application variable:

lucee.runtime.exp.ExpressionException: key [path] doesn't exist (existing keys:applicationname)
        at lucee.commons.collection.AbstractMapPro.invalidKey(AbstractMapPro.java:754)
        at lucee.commons.collection.LinkedHashMapPro.g(LinkedHashMapPro.java:201)
        at lucee.commons.collection.SyncMap.g(SyncMap.java:91)
        at lucee.runtime.type.StructImpl.get(StructImpl.java:128)
        at components.test_cfc$cf.initComponent(/components/test.cfc:4)
        at components.test_cfc$cf.newInstance(/components/test.cfc:1)
        at lucee.runtime.component.ComponentLoader.initComponent(ComponentLoader.java:548)
        at lucee.runtime.component.ComponentLoader._loadComponent(ComponentLoader.java:472)
        at lucee.runtime.component.ComponentLoader.load(ComponentLoader.java:410)
        at lucee.runtime.component.ComponentLoader._search(ComponentLoader.java:296)
        at lucee.runtime.component.ComponentLoader._search(ComponentLoader.java:120)
        at lucee.runtime.component.ComponentLoader.searchComponent(ComponentLoader.java:79)
        at lucee.runtime.PageContextImpl.loadComponent(PageContextImpl.java:3148)
        at test.TestClass$1.run(TestClass.java:64)

I’ve attached the mini-webapp and the maven project which is creating the thread. The java application is reading host etc from a property file (/test.properties) so that a recompile is not necessary to test

The webapp was installed and referenced as “test” and the reproduction can be started with test/index.cfm

test-webapp.zip (8.0 KB) java-project.zip (4.4 KB) test.properties (120 Bytes)

Thank you very much if you can find time to look into this and kind regards
Michael