I am porting a legacy application with about 500.0...
# lucee
c
I am porting a legacy application with about 500.000 lines of code (with horrible architecture, as usual πŸ˜‰) from ACF to Lucee. Most of the stuff requires just minor adjustments, but I have one case where an app specific mapping is not available inside a CFC and and therefore instantiation of another CFC instantiation fails. It's a case of
include cfm
->
include cfm
->
include cfm
->
include cfm
->
call CFC method
->
new mapped.path.OtherCFC()
. In the last cfm I can dump
this.mappings
and everything is there, but in the CFC method none of those are available. I tried
GetPageContext().getConfig().getApplicationMappings()
to see which mappings are available, but apparently that does not list app specific mappings. Does anybody have an idea how I could go about finding out why the mappings are "missing" or how to fix that?
g
are you using Application.cfc level mappings ? I understand these are only available within the same Application, global mappings are created in the Lucee admin ?
c
Application.cfc level... and it is within the same application
g
If you add the mapping to the Lucee Admin (server) - does it then work? If so - you, too, are a victim of LDEV-694 Please vote for it!
a
I think this is the case of application defined mappings being available at runtime but not compile time im guessing it works for cfincludes but not e.g in an extends statement
I think acf fudges this to make it work but lucee doesn't
g
The ticket I linked shows how ACF adds the context of the servlet container to the path - which Lucee does not yet do.
a
From memory I think this will work with lucee admin defined mappings and also the environment variable defined ones
g
Here is a Lucee forums thread, where @bdw429s steers me through it all (well for my use-case)
b
If you’re problem is runtime vs compile time and you are using CommandBox, you can use cfconfig to create the server level mappings automatically using a .cfconfig.json file. I believe cfconfig can be used outside of CommandBox too but I've never used it that way (not sure why anyone would really).
c
@gavinbaumanis this has nothing to do with webserver virtual mappings, as a matter of fact there is no webserver mapping for that specific directory.
@alexpixl8 actually the application defined mappings don't work for either extends or
new mapped.path.myCFC()
@bhartsfield no CommandBox involved so far
a
@chris-schmitz either I'm misunderstanding what you are doing in the code, or I cannot replicate it so there might be some other idiosyncrasy in play. Here's my attempt based on what you said: https://github.com/adamcameron/cfml/tree/lucee_mapping_issue/community/chrisSchmitz/luceeMappingsIssue This works A-OK on both CF2021 and Lucee
a
Yes @chris-schmitz I'm saying that both the extends and new calls will not work with mapping defined in Application.cfc
You will need to define them either in admin or by environment variables
@zackster maybe can chime in but my understanding is this is a difference between lucee and acf in terms of compile time vs runtime
a
I can reproduce a similar-seeming problem in ColdFusion where it does not respect
import
statements when using the unqualified class reference in an
extends
. But Lucee handles this fine. I cannot reproduce any issue with extends / new / import / fully-qualified / un-qualified names and runtime Application.cfc-defined mappings on Lucee. Which, to be honest, rather surprises me.
c
@Adam Cameron I tried to create a test case for the better part of this afternoon, too, and in that test case the mappings work, like you said. I tried to mimic the original application's structure and file names as much as possible, but still: test case works, actual application fails. But things got even more confusing... in the actual application the mapping is named
modul
(without an 'e', they use the German name here). If I do
fileExists( expandPath( 'modul/path/to/any.cfc'  ) )
in a CFC method, the file is found, so the mapping is working. If I do
new <http://modul.path.to|modul.path.to>.any()
right in the next line, it says the component can't be found. And the result is the same if I use the old fashioned
createObject()
instead. I then tried the appoach @cfsimplicity mentioned in https://blog.simplicityweb.co.uk/123/forcing-lucee-to-re-check-the-physical-paths-of-application-defined-mappings-without-a-restart ... and did a loop over
GetPageContext().getConfig().getApplicationMappings()
and displayed
getPhysical()
for every mapping ... and I found mappings of a different application (different application name). 😞
πŸ˜• 1
a
and I found mappings of a different application
That sounds like a smoking gun.
This is in dev, yeah? Can you restart Lucee entirely, and not hit that other app at all so there's zero chance its mappings load, and then retest the first app?
c
it's in a docker dev environment. I did that. several times... no change
a
Ok so where are these other mappings coming from then?
b
@chris-schmitz Do you see the same incorrect mappings when you output
getApplicationMetadata().mappings
. That is the documented way to get that data
In fact, just dump out the entire output of
getApplicationMetadata()
and it will have the application name and everything
Is it possible that at any point your code path moves inside of a closure that was possibly defined in another context? Just think of ways the current page context could get swapped to another one.
βœ… 1
c
Sorry, I was not clear... after the restart the other mappings were gone until that other application was hit. With "no change" I meant that I still cannot instantiate a CFC with a mapping path from within another CFC.
βœ… 1
b
Using an app-specific mapping does work in my experience for creating and extending CFC. ColdBox does this all the time since we auto-create a mapping that points to every module so you can do
new myModule.models.foo()
and I've never had an issue with it.
βœ… 1
If the issue is that your thread local page context has suddenly thought it was in another application, I'd trace the code path and find at what exact moment that happens.
c
@bdw429s in
getApplicationMetadata()
couple of values seem right, but some seem wrong, e.g. the mapping struct is empty
I usually do this as well ... even the application in question does this... but in this specific situation I can't get it to work
b
My recommendation here is what I usually recommend-- simplify the problem domain, keeping the errant behavior but eliminating as much stuff as possible until you can get it worked down to the simplest reproducible form. So basically, create a copy of this and start ripping out pieces until it's as simple as possible, but still breaks. Sometimes in doing so, you find a bug on your end, and if not, you finally have a nice stand-alone repro case you can use for the ticket πŸ™‚
βœ… 1
a
This isn't this stupid thing you and I have encountered before @bdw429s where like as well as the
/modul
mapping, there's also a dir at
/modul
in the file system, or in the web root (or application root? Can't remember) and Lucee is deciding that's what you mean instead of your same-named mapping?
b
That's a great question/point. A good test would be to change it to
/foo
and see if it changes the behavior
βœ… 1
The specific issue I've had in the past is when I'm running Lucee β€’ on *nix β€’ There is a folder at the ROOT of the file system with the same name as a CF mapping.
i.e. a mapping called
/opt
and the actual *nix file system as
/opt
as well
βœ… 1
a
I was also about to suggest start deleting stuff between where the code is going wrong and the initial file being hit. Keep removing code until the problem stops.
It's a pain in the butt and a bit ham-fisted, but it's quick and easy to do.
c
great points Adam and Brad, I got to go now, but, tomorrow I'll check this out!
a
Keep us posted mate.
c
Sorry for the hiatus in updating you, as I said in the Adobe channel, my time and energy were occupied by other events. iSorry for the hiatus, as I said in
However, I managed to boil it down to a small reproducable case...
So, to reproduce the error, your app needs to do the folllowing: 1. define the app specific mappings NOT in the pseudo constructor as we usually do, but in a request life cycle method, e.g.
onRequestStar()
or
onRequest()
2. Anywhere in the life cycle before defining the mappings, use
expandPath()
with an argument that starts with a "/"
I set up a small demo: https://github.com/chrisschmitz/luceeMappingIssue @Adam Cameron @bdw429s if you could find the time, I'd appreciate if you could verify (or falsify) my finding!
a
I'm actually surprised that mappings set in
onRequest
even works. I dunno why, but I would kinda expect all that sorta stuff to need to be set before the CFML engine starts to service the request. I have no basis for this thinking, but the practice seems... odd to me. Still: if it works at all, it should work uniformly, and should not be able to be thwarted by other CFML code. I note that neither CF nor Lucee actually document where in Application.cfc
this.mappings
ought to be set, both just say "in Application.cfc"
c
yeah, I use to set mappings in the pseudo constructor as well and was quite surprised that it was done differently here. I, too, could not find a hint where in Application.cfc you need to set the mappings.
LUCEE_MAPPING_FIRST sorry iPhone doesn't copy anchors and on a train to a lake south of Berlin
c
@zackster this does not have any impact on the behaviour, at least in my demo case
a
Can confirm, @chris-schmitz, I see the same thing you do
yeah Zack's idea doesn't seem very relevant to this
I mean... it sounds "adjacent" to this issue, that said
If I had to guess, the
expandPath
call kicks of some broader process that resolves all existing mappings (I guess it has to, given that dir doesn't exist, so Lucee needs to try to work out WTF yer on about), but thereafter that's it... no more checks.
Isn't there an application (or server / context?) setting to check mappings once per req, or every time?
Makes no difference if the
expandPath
call refers to an existant (file system) path
c
πŸ™Œ 1