Hi Jodi, I do this exact thing on a few projects. Mostly Rabbit message consumers which I execute inside a Task Runner inside CommandBox inside a MiniBox docker container, running on Docker Swarm. I re-use the business logic from my client’s web apps inside the Task Runners.
Now, there is a longish list of caveats that, depending on your specific code base, may be no issue or may require some refactoring.
- The business logic was already wrapped up in Box Modules, which can be loaded quickly and easily from inside CommandBox using the
loadModule()
function. This provides instant-use CF mappings, WireBox mappings, and interception points
- All of the 3rd party libs we’re depending on are also Box modules. e.g. RabbitSDK, CFCouchbase, Sentry, Hyper, etc which makes them all nicely encapsulated
- All of the business logic is from proper MVC app, so there is a nice, clear separation of concerns for services and views.
- The business logic has few or nor hard dependencies on the HTTP mechanics, application/server/request scopes, or the MVC framwork at all
- it is required to set up any datasources in the CLI that the code requires (this isn’t too hard), as well as any module config.
So, what you want to do is totally possible, but how easy it is will depend on a number of things on your end. For a Task Runner that loads up some stuff and waits in a while/true loop, you just need to catch an interrupted exception, which is what will happen when you stop the task. So something like this:
component {
function run() {
print.line( 'Task starting...' ).toConsole();
// Load modules, set up datasources, etc, etc
try {
while( true ) {
processRecords();
sleep( 500 );
}
} catch( java.lang.InterruptedException e ) {
print.line( 'Task interrupted' ).toConsole();
} finally {
// Logic here to clean up
print.line( 'Task shut down' ).toConsole();
}
}
}
Now, I did notice you mentioned ORM in your post. That’s probably going to pose some significant issues for you, mostly because
- Neither of the CF engines really ever accounted for Hibernate being used outside of a web server, and they have a lot of dependencies on
Application.cfc
, which doesn’t exist here.
- I’ve never tested our
cborm
module outside of ColdBox so I don’t know if it works. It probably can be made to work, but if cborm has any current hard dependencies on ColdBox, it’s not going to be happy being loaded up in CommandBox. That will take some fiddling to see if it works and what it takes to get Hibernate in general working. You’re probably going to need to test and see if
application
action="update",
ormSettings={};
is supported on Lucee (I’ve never tried it, honesty). Also, you didn’t mention if your web app is running on Adobe ColdFusion or Lucee Server, but CommandBox Task Runners execute on the latest stable Lucee version, so your CFML code will need to be compatible there as well.
This is something you need to address as well. ColdBox 3.x is old. Like REALLY old! We’re up to 6.7.0 now and 3.8 was 11 years ago (2013)! This means your app is likely still dependent on Plugins (which were removed entirely in ColdBox 4) and less likely to be broken into reusable modules (which were introduced in ColdBox 3, but really became a first-class citizen of the framework in v4).
So, you’ve got some pretty big things working against you, but I’m sure it’s all possible if you’re willing to commit the time to it. Being able to have CLI-based daemons running aync logic is super powerful and fun. Also, remember Ortus has consulting plans if your company wants us to work directly with getting this figured out.