Forcing Lucee to re-check the physical paths of application defined mappings without a restart
This post is a follow up to one of Ben's from almost a year ago in which he described Confusion Over this.mappings And expandPath() Not Working In Lucee.
What it boils down to is, as Ben says:
...the evaluation of thethis.mappings
paths gets "confused" ... if you attempt to reference a directory that does not yet exist
Take the following mapping defined in Application.cfc
this.mappings = {
"/test": "c:\abovewebroot\test"
};
When the application first runs, if the path "c:\abovewebroot\test" doesn't yet exist, Lucee won't throw an error but will instead resolve the "/test" mapping to a path below the web root, for example "c:\abovewebroot\www\test". This is the "confusion" Ben is talking about.
Fine, you might think, I'll just create the physical folder and all will be well.
Unfortunately not. Once evaluated, Lucee will cache that incorrect path value for the life of the server. In other words, the only way of getting the physical folder "picked up" again is to restart the engine.
Edge case?
As Ben says this isn't likely to be a common situation. For the most part you'd expect mapped paths to exist each time you fire up an application. But we recently bumped into it when migrating some applications to a new physical server. One particular mapping pointed to a dynamically named backup folder which wasn't created until a particular scheduled task had run for the first time on that machine.
Lucee therefore resolved the mapping to an incorrect path below the web root and any ExpandPath()
references continued to fail even after the task had run.
Restarting the engine fixed the issue, but it would have been much better to have been able to clear the cache (wherever that might be) or otherwise force Lucee to re-evaluate the path once it had been created, without the disruption of restarting a production server.
Unsupported workaround
I've raised a ticket for an official solution to the problem, but in the meantime I've discovered a "back-door" method which seems to be an effective way of forcing all of the current application's mappings to be instantly re-evaluated. Here it is wrapped as a one-line UDF.
void function recheckApplicationMappings(){
for( var mapping in GetPageContext().getConfig().getApplicationMapping() ) mapping.check();
}