I’m doing some stuff with Ably websockets and have made quite a bit of progress using their Java SDK. I think this will be a viable 3rd party websocket solution for Lucee - I’ll post my recipes and findings ASAP.
Here’s where I’m at:
I got the front end stuff working, and now I’m working on getting a listener running on the backend. I’ve got this working with some limitations:
When I make a channel listener CFC for Ably websockets, I’m using the function CreateDynamicProxy() which wraps my listener CFC with the java interface for the Ably Java SDK. Then the Ably Java SDK calls the method onMessage() in my listener CFC for each incoming message. This works great, but the application scope inside this method is basically blank. It’s not the same as the rest of my codebase, so it doesn’t have all the things attached to it, nor can I access things that are defined in it, like mappings, caches, etc.
I’m trying to leverage my existing codebase, which depends on stuff that’s setup in my application.cfc, including mappings, and other stuff attached to the application scope. I started to get around this by saving a reference to the application scope when I create the listener CFC, and then copying the stuff from my saved reference to the application scope in the onMessage() method. This works, but I still don’t have access to mappings and caches, etc.
My question is… is it at all possible to apply the correct application context from within the onMessage() callback that’s being called from the Ably Java SDK so that I have access to my application scope as well as all the mappings and other things?
I’ve run into this problem with the old websocket extension, as well as the new one. As a result, I had to re-implement a bunch of logic/database stuff specifically for websockets. I basically have to build a new app that does a lot of the same stuff.
It would be great to be able to ask the Lucee server to apply a specific application context for this type of scenario so I don’t have to build all this stuff again and I can leverage existing code in my app.
the difference between the application scope and the application context is key here
the scope being all the variables stored under application which are shared, the context is per request and isn’t shared, which means you can easily reconfigure a request on the fly to use preciseMath or full null support etc etc.
internalRequest
I think the solution to your problem is Lucee’s internalRequest function
It’s something which was added for our tests but is extremely useful and was unhidden in 6
it’s like CFHTTP, but without the overhead of networking etc and it errors into the current request
These are the tests I knocked up for the Lucee admin, using internal request, I got really tired of some obscure page in the admin being broken by some change but only finding out after we made a release.
Can you imagine how this could work or do I need to explain it further?
Because the application context is different when calls are made into my CFC that was wrapped with CreateDynamicProxy(), I was trying to create an identical application scope so my downstream code that depends on the application scope. This almost works, but because the rest of the application context (mappings, etc) doesn’t exist, this approach doesn’t work.
I’m wondering if the call to CreateDynamicProxy() could be modified to take an additional application name so that it could somehow inject the specified application context into calls that are made into the CFC. I have no idea how feasible something like this is, but if possible, seems like it would solve some problems.
Something else I should mention… I haven’t needed to use any channel listeners with Ably websockets because of how that platform works. Authenticating into a websocket is done via an ajax call, and all you have to do to establish a channel is give it a name and reference it. It’s incredibly easy to send out messages to channels from the backend without having a listener in place, so at this point I may not even need to use listeners. That said, I have been able to create a listener and do a lot with it since every onMessage() call includes a clientId (a userID or whatever you want), which you set when you subscribe to the channel on the front end.