[coldbox] ModuleConfig / handlersLocation - dealing with handlers outside the module directory

The handlersLocation configuration doesn’t allow specifying files outside the directory the ModuleConfig.cfc is in - using either mappings or relative paths fail, due to ModuleService.cfc effectively doing this:

handlerInvocationPath = modulesInvocationPath & “.” & modName & “.#replace(mConfig.conventions.handlersLocation,”/",".",“all”)#";

handlerPhysicalPath = modLocation & “/#mConfig.conventions.handlersLocation#”;

So… it seems I need to override handlerInvocationPath and handlerPhysicalPath to make it work, but I can’t figure out the appropriate place to do it.

Alternatively, I’m thinking ModuleService.cfc could be updated to allow a mapping to work, something like:

if ( mConfig.conventions.handlersLocation.startsWith(’/’) )
{
mConfig.handlerInvocationPath = replace(mConfig.conventions.handlersLocation.substring(1),"/",".",“all”);
mConfig.handlerPhysicalPath = expandPath(mConfig.conventions.handlersLocation);
}
else
{
mConfig.handlerInvocationPath &= “.#replace(mConfig.conventions.handlersLocation,”/",".",“all”)#";
mConfig.handlerPhysicalPath &= “/#mConfig.conventions.handlersLocation#”;
}

Is there any reason that’s not a valid change to make?

Relative paths should not fail, as it is always relative to the module anyway. As for the rest of your question, can you explain what it is you are trying to achieve, there are many ways to use the parent conventions, but that will dpened on what it is your actually doing or attempting to do.

Using relative paths - that is “…/…/…/path/to/files” - works for Views and Layouts, but not Handlers - due to the code I highlighted.

What I’m trying to do is point at handlers that are outside the module directory, because the alternative is to copy them inside the directory and maintain two copies of every file, which is obviously not desirable.

There are two separate copies of the same module because the same functionality is used in two different applications, and - due to Hibernate - each copy needs to have its own model, otherwise it can’t find things.

Hmm, I’m not sure if I’ve clearly described the situation there, but right now I need to eat and stuff - will update in an hour or so with a better description.

Yes but the handlersLocation is a convention of its name. So if you change it to, lets say controllers, then it would use the folder ‘controllers’ in the module. If you are looking for external references, then you should be looking at the parent settings for that and the external location setting maybe.

Modules, by design, are to be self-contained. Parent lookups should be used to inherit from the parent app. Please expand on your ORM issues. There should be a way to solve that. For instance, a ContentBox app has the CFCLocation set to /model and /modules which picks up ORM entities in both places.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Yeah, the problem I think is at least in part due to the architecture - we’ve got modules done more as segregating functionality rather than truly being self-contained. :confused:

So, taking a step back, we’ve got two distinct Coldbox applications: a central core and the main webapp.

There’s a single core database plus individual databases for each instance of the main webapp.

Aside from what I’m trying to do at the moment, there are no shared modules - the two apps are mostly independent (they communicate over an API and share some plugins, global layout, and so on, but are generally doing separate things).

So, what I’ve now got is two modules that currently work on the main webapp, and the task is to get them working on core.

The pair of modules are almost entirely self-contained (between themselves) - they are each called by other code, but only reference themselves and each other in all but one case - a single entity has a single FK column reference to an entity in the main webapp (basically a user), and to make it work in the core app I need to reference the equivalent user entity in the core app model.

So yeah, if I could remove that single property, and inject it dynamically based on which application the module is being used by, I could have a single copy of the code and all would be fine - but if that’s possible I don’t know how to do it. (Of course, if this wasn’t all Hibernate-based it would be trivial, but I wont get into a rant about that.)

My compromise to avoid copying the entire code for the two modules is to copy just the model (with relevant tweaks) and setup ModuleConfig to to refer to the existing handlers/etc - this only works with the code change to ModuleService.cfc as described earlier.

Setting CFCLocation to point at the location of the original modules would result in Hibernate either not being able to find the user FK entity, or (if that location was also added) dumping a whole bunch of tables into the core database.

So… that’s hopefully a sufficiently clear explanation? Even though this isn’t an ideal/intended architecture, it does seem that updating handlersLocation to work with mappings is a simple solution that would not get in the way of people doing things the standard way?
Of course if there are other solutions that mean avoiding having to maintain duplicate code then that’d be great too.

DSL, reference them by name with wirebox.

Damn, I don’t think that will work with Entities, but you could try it.

http://www.andyscott.id.au/blog/using-interceptors-in-coldbox-for-greater-scalabaility

When I read this more, I don’t see the association in changing the handlers for ORM. If there is common code in the handler extend to a base, or am I not understanding how the handler and ORM are integrated. Is it just the model problem you explained, if that is the case I suggest switching them out at run time.

The handler issue is just my attempt to avoid copying the entire module code.

At the moment there is the same module twice, but one has only the model code and is referencing the original version of the module for the rest of the code (handlers/views/layouts - and for views/layouts I can use … addressing so that’s not a problem).

So basically the handlers issue is just a side-effect of needing to have two copies of the model, and not wanting to duplicate (and thus maintain) everything.

And the only reason I need that copy is because one of the entities has this property:

property
name=“Person”
fieldtype=“many-to-one”
cfc=“library.modules.person.model.Person”
fkcolumn=“PersonId”
lazy=true
;

And the CFC “library.modules.person.model.Person” is meaningless for the core application - to make it work there it needs to be:

property
name=“Person”
fieldtype=“many-to-one”
cfc=“home.model.CorePerson”
fkcolumn=“PersonId”
lazy=true
;

If I could dynamically swap between those cfc attributes based on some per-application thing, I could have a single copy of the module and everything else would be a non-issue.

But, AFAIK, CF/Hibernate doesn’t offer any runtime interaction - it does its stuff in Application.cfc (based on This.OrmSettings) when it starts up (or when OrmReload() is called) and it needs some form of Person property at that time to work.

I’ve been trying to think if there’s some form of aliasing/proxying that could do it, but I don’t think there is - Wirebox could theoretically solve this, but obviously it’s not around at the point that Hibernate is doing its stuff.

Trying to do cfc="#Application.PersonCfc#" results in error “Expression in cfproperty value must have a constant value.”

So you can’t move the relationships into a base entity? That would solve all your issues.

I think Application mappings will work here..

Regards,
Andrew Scott
WebSite: http://www.andyscott.id.au/
Google+: http://plus.google.com/113032480415921517411

So you can’t move the relationships into a base entity?

Oh… so create a new “CommonPerson” CFC that is extended by both library.modules.person.model.Person and home.model.CorePerson and then have this entity reference that new CFC instead.

That sounds like it should work. I’ll give it a go tomorrow and post if it does.

In theory, but I am not sure how it would work if that parent is used in the cfc, theory dictates that when you reference the child the parent PK should be intact.