Extension onRequestStart

Hello,
i want to create a extension which execute some tasks at request start (like onRequestStart in Application.cfc, but via extension).
Is there a way to do it with cfml/java?
In the docs (Extensions in Lucee 5 :: Lucee Documentation) i just found examples, for tags/functions/context (webservices etc.) but not for hooking into a request.

Thank you :slight_smile:

Push… Would be nice if someone has a hint for me. :slight_smile:

I wish CFML had a way to register listeners like onRequestStart in CFML :confused: I don’t know if there’s a way to do it in Java. Probably, but who knows if it’s supported. Really @micstriit is probably the only person who knows the answer.

throws @bdw429s a side eye :wink:

I have looked into it before (I wanted to create an extension for FuseGuard to fire automatically onRequestStart), I don’t think there is an easy way to do it within the current extension api, but I would love to hear otherwise.

Pete Freitag
Foundeo Inc.

NO that is not possible, Lucee comes with different Listeners depending on the setting made for listener type (modern,mixed,classic), but the difference simply is between Application.cfc or application.cfm or both. In theory it would be possible to create a custom Listener that extends for example the MixedListener that also allows hocks, problemyyou can not register it, Lucee does not allow to register new custom listeners, but that would be easy to change.

But i think the more important question is, what do you wanna to achieve exactly?

@micstriit I think Pete gave an excellent example above. Another eaxmple would be for frameworks to automatically listen to request, session, or application lifecycle events without requiring the user to put boilerplate in their Application.cfc. Really, forcing users to first of all even HAVE an Application.cfc (ahem, JSR-223!!!) and secondly forcing settings and code to be in that file is a major limitation of CFML.

  • What if I want to register my own listener from inside a 3rd party module that runs on request start for security?
  • What if I want to register my own listener from inside a framework that loads the framework on application start?
  • What if I want a framework that can automatically respond to missing templates, request errors, session start/end without creating boilerplate methods?
  • What if I want to ensure the ColdBox listeners run even if the user forgets and implements their own onSessionStart() method and forgets to delegate to the ColdBox bootstrap?

There are so many uses for the idea of custom listeners and I’ve wanted to do this for many years, whether through an extension or just CFML itself.

@micstriit my use case is to create a FuseGuard extension for Lucee that inspects the request for malicious input onRequestStart and before the rest of your application code runs (so it can block the request if necessary). Currently to enable FuseGuard you have to insert some code in onRequestStart to invoke FuseGuard in your application, but I’d like to eliminate that step as it can be tedious if you have a ton of Application.cfc / cfm files.

I know it would be technically possible to do this using a ServletFilter and CFCProxy (FuseGuard is written in CFML) or JSR-233 but I think that would be horribly inefficient way to accomplish it, so I’ve never gone that route.

which exact entry points do people want, i.e. before or after application.cfc listeners?

  • onBeforeRequestStart
  • onAfterRequestStart

etc etc…

1 Like

I would just be happy to be able to register the same listeners that the Application.cfc does. without creating any new ones. No matter what you do, you will deal with the issue of one listener wanting to run before another listener and I’m not aware of a way to really accommodate everything.

In other words-- Pete wants his code to run before the user’s onRequestStart() so you create an onBeforeRequestStart() Well, now I have some code I want to run BEFORE Pete’s code. So now we need an onBeforeBeforeRequestStart()!

It never really ends. As soon as you have a system that allows 3rd party libraries to register their own listeners in a vacuum, you deal with who gets to go first/last. Coldbox has this same issue with modules all registering a preProcess() interceptor, for example.

You can simplify it a bit if you adopt an “around handler” or AOP sort of approach (think servlet filters) where you require the code to explicitly proceed to the next call. This allows before/after/around advice all in a single mechanism, but it requires more boilerplate and is trickier to implement. It also does nothing to solve the ordering issue-- it just combines the before/after into a single unit.

I would be tempted to adopt something that is slightly more opinionated just for simplicity:

  • Listeners configured at a server level (such as from an extension) fire first
  • Listeners defined as methods in the Application.cfc fire next
  • Listeners defined ad-hoc via CFML (presumably via cfapplication action=update fire last

One possibility with the 3rd bullet is the array of existing listeners could be exposed via getApplicationMetadata() in the same way datsources or caches are already defined. This would allow you to inject your UDF in the array in the position you wanted. (prepend/append).

Thanks for all the information already.
My usecase ist the same as @pfreitag i would like to inspect the request for malicious input onRequestStart and before the rest of the application code runs.
So a onBeforeRequestStart-function would be nice.

But it really seems to be a bigger task as i thought.

this is the interface used by Lucee for the internal listeners
https://javadoc.lucee.org/lucee/runtime/listener/ApplicationListener.html

But 1 things is missing to achieve this:
The possibility that an extension can register a custom listener that does NOT replace the existing one, just extend them.
I will digg a little bit more into this to see how complicated it would be to achieve this.

1 Like

I have filed an enhancement [LDEV-3792] allow extensions to register listeners - Lucee

3 Likes

Just my 2-cents here, but in general, I try to avoid anything that is “magic”. Meaning, if code is executing, but it’s not clear why it is executing or where it is being defined, it can lead to problems. Personally, I don’t think there is anything wrong with requiring a user to add a little bit of code to the onRequestStart() event-handler to invoke something. This way, everyone can easily see where it is coming from.

I know this isn’t the point of the thread. I just wanted to give one user’s perspective that having explicit code to show something is actually comforting (at least to me).

Here is my 2 cents, and this isnt a rant or if seems terse, I apologize in advance.

Everyone is going about this wrong from what I understand of JAVA.
Java on start, takes everything in its config and throws it its own “Universe” where it starts to execute
This includes ColdFusion

Instead of trying to load everything as “Static” my cool new .java.class for something
create “cool.new.java.class” as a place holder
The place holder has to be in two parts
Place holder memory and place holder, on application restart
This could be a configuration option. Much like Lucee or ACF or any java extension, instead of trying to SHOVE a whole binary class with new code, create the “cool.new.java.class” as nothing more than an API hook that
reads and stores applications that should be “Hot-loaded”.
Nothing different that what Java does now in any application, save for carving out a slice of memory before the whole application stack on load understands its loaded. The side “Hotloaded” jar designed to be extended as an API to further load more JARS that must conform to an open standard (COLDFUSION)
It then could on setting function “install” upon restart or “run” as needed via API and API function could be extend to infinity based upon configuration.

that would put this platform beyond anything in the enterprise currently has now, and yes, it IS possible. Nobody has just done it yet.

EDIT – Someone wrote how to do this is JSP files, the same option could be further extended to lucee. Learn Tomcat to dynamically load the JSP Class class - Programmer All

I can tell how another project (Apache James Mailserver) handles this.
You can write your plugin and extend/implement the class you want to hook into (e.g. Mailet for handling new incoming mail).
There you can override the default methods and customize your request data.
Then there is an xml configuration (+ extra plugin parameters) in which order the plugin hooks should be processed.
Maybe that would be a good solution.