Application.cfc methods unavailable to display templates?

I’m on Lucee 5.3.10.120, and found that calling a public method defined in my Application.cfc from a display template doesn’t work. Hasn’t that always worked in the past? I’m not talking about a lifecycle method or anything.

Say my Application.cfc contains this:

public function getFoo() { return "bar"; }

From within any cfm file in that application, shouldn’t I be able to call getFoo() ?

If you use the onRequest() event-handler to execute the template, then it works:

public void function onRequest( scriptName ) {
    include scriptName;
}

This essentially executes the script as a “mixin” within the Application.cfc, executing it in the same page context.

But, if you omit the onRequest() event handler, then the page variables scope is separate from the Application.cfc instance variable scope. I don’t believe this has ever been different. But, I’m not 100% sure.

1 Like

I think also some frameworks basically do this for you. FW/1, as an example, I believe renders your view templates in the context of the Application.cfc, much like I described above. From the FW/1 Docs:

All views execute as included files within the context of a FW/1 request, i.e., inside the current request’s instance of Application.cfc. That means that all methods inside FW/1 and inside your Application.cfc are available directly inside your views. See the public API documentation below for what you can and should use of those methods! This means that you can have view helper methods in your Application.cfc, either directly or via an include of a library file.

So, perhaps that’s what you’re thinking of?

oh, wow. I didn’t even notice this app didn’t have an onRequest method. I’m 100% used to working in FW/1, and everything seems dumb without it now. That explains it! Thanks, Ben!

2 Likes

“everything seems dumb without it now.” :laughing: :laughing: I am sure that this might tickle @seancorfield to know. Glad I could help!

2 Likes

I’m sure I’ve told @seancorfield I appreciate his work before, but it’s been a while. I worked in CF for a long time, and when FW/1 came along, it was everything I’d wished Fusebox would be. I even remember when Sean took over Fusebox and made it kind of a big step closer to what would become FW/1. I used FW/1 for every project for years, and then did non-CF work for another long time, and just came back to CF a year ago because of a new job. It aggravates me every day that this codebase isn’t in FW/1.

1 Like

We use FW/1 at work as well. It’s been really nice and simple and gets the job done.

The one thing I wish it had (and maybe newer versions do) is a way to do the dependency-injection in a manner that doesn’t require all CFCs to be globally uniquely named. We end up with some very long component names to keep things unique. But, I usually get around this by overriding the setter methods for property and then renaming the object locally.

If you only want a subset of your CFCs to be available for injection, you could put them in a specific folder and tell DI/1 to only scan that folder. They still have to have unique names so that DI/1 can figure out which injected properties in code refer to which CFC instances :slight_smile:

1 Like

I think this often comes up for me when I have a group of cohesive components that only get used together. For example, I might have a Service component (business logic) that depends on a Data Gateway component (persistence); and, I’d love to be able to something like:

component displayName="ThingService" {

    property name="gateway" type="com.features.thing.ThingGateway";

}

So that I could then just use variables.gateway internally.

Right now, I achieve this by just renaming it on “Set”:

component displayName="ThingService" {

    property thingGateway;

    public void function setThingGateway( thingGateway ) {

        variables.gateway = arguments.thingGateway;

    }
}

But, this isn’t so much work - I’m used to doing it. I’m just thinking out loud.

1 Like

Why not define the function in question inside onApplicationStart() and then put it in the Application scope?

public boolean function onApplicationStart() {
	...
	function getFoo() { return "bar"; }
	Application.getFoo = getFoo;
	...
}

This way it can be called from any template as Application.getFoo() without the need of onRequest() event-handler. Or is this a bad approach for some reason?

1 Like

seems like a valid way to do it. my question was more about my confusion about application methods being automatically available within cfm files’ variables scope, a mistaken impression that came from being so used to using FW/1 that I thought the ability to do that was a normal part of how CF functions.