> Coldbox-dependent modules are incompatible with CommandBox
That is correct. Any Box module which references CFCs or WireBox DLSs that are unique to the ColdBox framework will throw errors if they tried to load up inside of the CommandBox “framework”.
> CommandBox is module-aware, but uses its own Wirebox instance which requires specific DSL (slightly different from the Coldbox one)
Mostly-- WireBox still works the same way (and is actually a complete standalone DI solution outside of anything else). When WireBox is used inside of ColdBox, there are additional injection namespaces registered to allow you to request instances of services from within Coldbox. And the same is true of CommandBox. It also registers its own custom set of injection namespaces with WireBox to allow you to get instances of CommandBox services easily. The trick is that both ColdBox and CommandBox have a “ModuleService” but their injection DSLs differ so it’s not super easy to write a module that can work across both if that module needs to get access to the ModuleService.
In ColdBox, you inject the ModuleService like so:
property name=“ModuleService” inject=“coldbox:moduleService”;
And in CommandBox, it looks like this:
property name=“ModuleService” inject=“moduleService”;
Now that doesn’t mean that every injection DSL is different, just a few of them that overlap. I’ve also considered adding aliases into CommandBox’s WireBox namespaces so DLSs like “coldbox:moduleservice” resolve to the same thing as a sort of compatibility layer.
> I still have no idea if there is any MongoDB CF wrapper available for CommandBox
No. The answer is “no”. At least not anything specifically made to work with CommandBox. That said, any library that was nothing more than a stand-alone CFC should work just fine. Also, like we discussed, the existing module could be made to work, it would just need massaged a bit. To be honest, you’re on the cutting edge here as people are really just now starting to pick up things like CommandBox tasks for heavy duty CFML-from-the-CLI operations. Don’t expect there to be a lot already out there, but please do be a part of creating it!
> Regarding the 2nd point: do all modules need to be installed in the CommandBox main installation directory (using the --system flag), or can a module installed in a local folder (where -say- tasks reside) can be used too?
CommandBox can literally load modules from anywhere. Well, more specifically, the ModuleService can do that. I think I already mentioned earlier the external modules location which is an arbitrary folder on your hard drive you can specify of global modules to load. In fact, CommandBox actually has THREE modules folders is loads from out of the box. There’s /cfml/modules, /cfml/system/modules, and /cfml/system/modules_app.
Now, regarding your question of loading arbitrary modules from the current folder, yes that is possible but I haven’t written anything to do it out of the box yet, I think this would be very cool, but there’s a lot of questions we’d need to answer first. Luis and I have actually been discussing this very thing. Here is a ticket we recently put in:
https://ortussolutions.atlassian.net/browse/COMMANDBOX-669
In the meantime, you should be able to do exactly what you want with just a few lines of code. Let’s say you have a module sitting in a "local’ folder to the task that you’re in, here’s a quick of example of how you could load arbitrary modules into CommandBox at run time. Please note however, that these modules wouldn’t “unload” by default and would stay in memory if the CLI stays open as part of the interactive shell. This would be fairly trivial to make a built-in part of tasks, but we just have to think through all the implications and decide if it’s what we want.
For this test, I created a simple task, whose code is below, and in the same folder as the task is a module_app folder that has a folder called “brad” inside of it which contains a simple module containing a “bradService.cfc” in the models folder (which will be automatically loaded when the module is registered.
component {
property name=‘moduleService’ inject=‘ModuleService’;
function run() {
// Generate a CF mapping that points to the module’s folder
var relativeModulePath = fileSystemUtil.makePathRelative( getCWD() & ‘modules_app’ );
moduleService.registerAndActivateModule( ‘brad’, relativeModulePath );
// Now use the module
print.line( getInstance( ‘bradService@brad’ ).doSomething() );
}
}
So in this way, you can arbitrarily load any module you want at run time inside of your task and everything from the module will instantly be available including WireBox mappings, module settings, interceptors, and custom CommandBox commands. The only two tricks really just creating a relative path and then asking the module service to load up the module. My thought is that it would be pretty easy for me to wrap up those two lines in a helper like this:
require( “modules_app/brad” );
Just brainstorming, but it would allow people to load arbitrary stuff that’s specific to a single project. The only real downside is that if you had a “brad” module in 5 different projects, and then you ran tasks from all 5 projects from inside the CommandBox interactive shell, you’d be loading 5 different “brad” modules which could start polluting the CommandBox framework.
Thanks!
~Brad
ColdBox/CommandBox Developer Advocate
Ortus Solutions, Corp
E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com