Understanding application.cfc location, webroot, appBase, and docBase

Hi All,
I’m porting an ancient CF9 app to Lucee and getting very confused about the location of the Application.cfc and a few terms like like appBase, docBase, and webroot. I feel like an idiot. :roll_eyes:

Set Up
I launched a copy (AMI) of the existing windows 2016 server and the running CF902 app. Check everything was fine in CF9.
Installed Lucee using the installer knowing it would also install BonCode(all-sites) and mod_cfml.

I went into the IIS site for the CF9 Admin and I shimmied the BonCode handlers down below the ACF handlers and the old CFAdmin started working (on CF9) again. Great.

Then I tried to run the main app (in Lucee).
The error was in Lucee colours so that was a good start but it seemed the request had nothing from the Application.cfc.

Importantly, this app has two access points. The app root (at least the way I think about it) in the example below is the app-one folder which holds the Application.cfc and lots of other code and folders.
In two of those sub folders are different entry points to the app.

The setting in the Lucee Admin is looking in the webroot and up.

Current to root (CFML default)
Looks for the file “Application.cfc/Application.cfm” from the current up to the webroot directory.

I note the webroot shown in the Lucee Admin is not app-one. It’s one of the entry points.

When I move the Application.cfc into the entry point folder it works (aside from other errors due to the moved application.cfc).

My question is;
How do I tell Lucee the webroot (appRoot? docBase? appBase?) is D:\CODE\app-one and what are those other terms I have seen in my hours of reading and searching.

I want to add I have never used Tomcat or BonCode or mod_cfml so I am swimming in a sea of ignorance - it’s like treacle. I’ve spent an embarrassing amount of time on this and I’m frazzled.

Thank you in advance.

OS: Windows Server 2016 64bit
Java Version: 11.0.19 (Eclipse Adoptium) 64bit
Tomcat Version: Apache Tomcat/9.0.76
Lucee Version: Lucee
IIS: Yes and I’m sorry :smiley:
BonCode: Yes
mod_cfml: Yes

Like many, brother. Dont worry.

To tell Lucee to use Application.cfc outside the webroot you need to use a mapping:

Don’t do it from code, but use Lucee’s admin.
When you have that:

appOneRoot = d:\code\app-one

then you can extend your Application.cfc (inside /public and /manager):
<cfcomponent extends="appOneRoot.Application">

Throw it all away. Use only CommandBox, if you can.


Thank you SO freaking much. I’ve got that running.

It’s a massive app, nearly 20 years old, and I was dreading doing this migration. I know there is still a long way to go of course.

It seems an unusual way to do it but I’m confident much smarter minds than mine made it that way for a good reason.

Yes, I knew I’d get pointed at CommandBox and I’ve got Monday set aside to do this all again to try that out.
I’m a glutton for punishment. :smiley:

Thank you again.



I understand your dealing with a legacy codebase.

It’s been my policy (for about 20 years) to Avoid depending on the Administrator Lucee | ACF. I’ve seen people go Nutz in there, setting up all sorts of things which makes migrations an absolute nightmare. I understand it’s too late for you now so ya just got to grind through it.

But here is something you might find helpful for the future.

This code autodetects the it’s own directory by finding the application.cfc
Once you know where that is you know your Application ROOT.
Then I set it in the application as :

This way you can have as many independent applications as you like, all without ever dealing with paths in the Administrator. This practice has had other benefits such as being able to ZIP the ColdFusion CFIDE folder when I’m not using it. The CFIDE is an Ancient Attack vector… They Always go for the Admin. So : when I ZIP it up there is nothing to attack.

When I need to adjust something like a DSN : I just un-zip it Set it… and then immediately Re-ZIP the entire CFIDE directory.

Here is what I use to autodetect and then sett my Application ROOT (and subsequently all others within). Perhaps you will find this useful.

** Note : AppRoot is just Coincidentally the name I chose (nothing to do with any standards. Now that I think about it. I should probably change it to a non-conflicting name.

/* 0.ReSet Application	*/
/* Auto Find AppRoot: Find Application.cfc root folder. Result is variable application.AppRoot */
application.AppRoot = ListDeleteAt(GetTemplatePath(),ListLen(GetTemplatePath(),"\"),"\");
for(LCount=1;LCount LTE ListLen(application.AppRoot,"\");LCount=LCount+1){if(FileExists("#application.AppRoot#\application.cfc")){break;};application.AppRoot = ListDeleteAt(application.AppRoot,ListLen(application.AppRoot,"\"),"\");};
/* END : Auto Find AppRoot: */

1 Like

Thanks Jay, that’s an interesting solution.

Given this is a monolith type setup my (real/main/root) Application.cfc is known and static so I have elected to proxy it to the Application.cfcs located at the different web roots (and in the end I did this using relative paths so no map was needed).

I’m so used to ACF not caring about the web root for this and just looking up the tree until it finds an Application.cfc.

I admit I’m still quite confused about the interplay of the Lucee context with maps and IIS virtual directories etc. I’m pushing on with CommandBox and, much as I expected, that is opening an even deeper chasm of ignorance for me. Sometimes I think I am in the wrong game. :laughing:

If we run out of things to learn, life would be boring!!


Hahahahaha!!! Welcome to the club!!! And you know what? I think everyone, I mean literary “EVERYONE” needs to fall into the rabbit whole of the great question:

What’s the secret about “Tomcats appBase vs. docBase”?

It’s like Neo’s first jump in the “Jump Programm” in the SciFi-Film Matrix. Everybody fails it! As you can see, even Railos/Lucees (and Tomcat committer) very respected guru @isapir failed this one (see it here). More confusing is that he doesn’t (in my opinion) get an appropriate answer to his question there too. I’ll try to explain with my own words (and my own perspective). I would have wished to have such when I failed my “jump” with Railo :smiley:

As far as I understand, the attributes docBase and appBase have a historical context with Tomcat!

Tomcat was primary built as a Java-Engine to allow serving Java-Applications for the Web. So they created a global directory were you can throw all these Java-Applications into that directory as .war-files. That directory is defined with the appBase-attribute inside the <host ...>-directive in server.xml. It follows the convention that the name of the .war file is also the web path name for the application. The convention also defines that the web path served at “/” (without having any other characters for the path name) need the file to be named ROOT.war. So if you throw a Java-Web-Archive named “ROOT.war” into the directory for the appBase, Tomcat will deploy and serve that specific application at http://some.domain.com/.

So, when using a configuration in the server.xml:

// server.xml
<host name="some.domain.com" appBase="/opt/tomcat/webapps" ... >

and adding the following .war files to the appBase will follow a naming convention to serve with the paths as follows:

/opt/tomcat/webapps/ROOT.war serves => http://some.domain.com/
/opt/tomcat/webapps/administrator.war serves=> http://some.domain.com/administrator
/opt/tomcat/webapps/messaging.war serves=> http://some.domain.com/messaging

This means, appBase is a global directory location where Tomcat will deploy all those applications and serve them to the web by convention.

Note: the file types are not limited to .war, e.g. these can also be simple directories.

/opt/tomcat/webapps/ROOT.war (compressed Java Web Archive)
                      |-- some.jar
                      |-- somethin.jsp
                      |-- someOtherDirectory
                                |-- someelse.jar
                                |-- somethinelse.jsp

/opt/tomcat/webapps/ROOT/   (uncompressed as directory)
                      |-- some.jar
                      |-- somethin.jsp
                      |-- someOtherDirectory
                                |-- someelse.jar
                                |-- somethinelse.jsp

But what happens if you really need to break that convention? What would you need to do? That’s were the docBase in the Tomcats <context ...> directive comes into play. It allows you to serve such Java application by defining a web path name and reference it to a specific custom .war file (or directory).

(In older Tomcat versions) you would typically do that like so:

// server.xml
<host name= "some.domain.com" appBase="/opt/tomcat/webapps">
    <!-- serves at http://some.domain.com/ -->
    <Context path="/" docBase="/opt/wars/myownCustomRoot.war">

    <!-- serves at http://some.domain.com/administrator -->
    <context path="/administrator" docBase="/opt/wars/e259a62a-c516-4737-9eab-77ac6b6e2bf9.war">

    <!-- serves at http://some.domain.com/messaging -->
    <Context path="/messaging" docBase="/opt/wars/ab4b7610-ad6e-4df8-a76e-db139d6c2d3a.war">

`If you understand that convention, you will also understand WHY the Lucee default application is ALWAYS installed with the /webapps/ROOT.

At some point (I think from Tomcat 8 upwards) the Apache Tomcat Team changed the configuration above. The above still works, but it’s not recommended anymore . Since Tomcat 8, you shouldn’t specify the docBase in the <context > directive within the body of the <host> directive anymore: Instead you should create an .xml configuration file following a very similar convention… like so:

For serving http://some.domain.com/:

// configuration file located at /opt/tomcat/conf/catalina/some.domain.com/ROOT.xml
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/opt/wars/myownCustomRoot.war">

For serving http://some.domain.com/administrator

//  configuration file located at /opt/tomcat/conf/catalina/some.domain.com/administrator.xml
// to serve at http://some.domain.com/administrator
<?xml version='1.0' encoding='utf-8'?>
  <Context docBase="/opt/wars/e259a62a-c516-4737-9eab-77ac6b6e2bf9.war">

For serving http://some.domain.com/messaging

//  configuration file located at /opt/tomcat/conf/catalina/some.domain.com/messaging.xml
// to serve at http://some.domain.com/messaging
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/opt/wars/ab4b7610-ad6e-4df8-a76e-db139d6c2d3a.war">

Note that the “path” attribute now doesn’t exist in that <context>-directive, because it’s set by the file name (convention) of ROOT.xml, administrator.xml and messaging.xml file! Also, all the configuration that were formely in the body of the <context>-directive of the server.xml file are now set here too!
The confusion comes because nowadays we don’t use Tomcat like that anymore. We usually serve only one application served in one webroot. Everything else is inside that application.

The good thing is:
mod_cfml that is shipped with the Lucee Installer takes care of that all for you. It does all those settings automagically.

The bad thing:
If you need to do certain settings manually and set them up incorrectly, you might get into trouble. Especially if you set the docBase equally with the appBase, as it happened once to @ensemblebd as showed here.

As I said, everyone who is new to Tomcat is likely to fail the Matirx-Like Tomcat-Jump here :smiley: … and I felll also a lot like you!!!

A warm hugh and welcome!!!


Firstly, huge props for the amazing reply. :open_mouth:

I’m going to need time to digest that.

My immediate takeaway, though, is to not use Tomcat :laughing:

Seriously though, thanks for the comprehensive response. I will be coming back to reference and understand it once I have a handle on CommandBox. :+1:

1 Like

@JeMit, If you are using CommandBox, be aware that this does not use Tomcat, but Undertow. I am not sure if that changes anything or not.

1 Like

What is awesome from commandbox is that you can do soooo much with its config files. You don’t need to dig into anything about Undertow. You can do almost everything by just adding it to the server.json files. From server rules through basic auth, ajp connection and you can even block Lucees Administrator there. If I’d be new to Lucee I’d check out commanbox also. At the time I started with Tomcat because I wanted to have one instance serving multi-sites, and at that time that was a diffcult issue with CommandBox. Now that’s history. But even if you are running on Tomcat, CommandBox is a MUST HAVE tool.


Yep, that’s why there’s a little bit of truth to my tongue in cheek comment about not using Tomcat. :grimacing:

Cheers for making sure I was clear on it though :+1:

1 Like

Yep @andreas, I’m loving CommandBox (even if I’m still in the slightly frustrating stage of learning).

After a few days of pulling my hair out :robot: (a diminishing resource) and listening to Brads video more than 50 times, I seem to have the system running side by side where the client can, via a dedicated sub-domain, access either the CF9 version or the Lucee version (just while extensive testing goes on over the next few months, then 100% Lucee).

The only thing I still need to figure out is processing of the PDF (the system builds up a certificate made of text data, signature (vector), branding (vector), and background (vector). I don’t think I will have time to figure out how to make Lucee do the PDF build (it does run, but Lucee is converting vector elements to pixel based images plus the formatting is a bit cactus and I’m all consumed bedding down this higher level stuff right now) so I might need to run that under ACF9 just for now and hit it as a service from the Lucee running app.

Amongst all of this is a long term goal to move to Docker which I have used (.Net app) in the past and love.

Thanks everyone who contributed.
I can see the light at the end of the tunnel - I’m hoping it’s not a train of course.

:robot: I really lost a lot of time to the “No connection could be made because the target machine actively refused it” even though all settings seemed perfect. I realised it was the hand off from IIS to AJP but all the settings seemed fine. The lucee server was in the right directory, the BonCode port and server.json port matched and I could hit it directly (skipping IIS) fine. I ended up ‘forgetting’ the Lucee server and resetting it up. I can’t see any significant difference in settings (I saved them all) but it works fine now :confused:

1 Like

This is a good resource about relative mapping:


Thanks @Roberto_Marzialetti, I had studied that article - it’s a great reference. :+1: