Migrating to Lucee from Adobe CF

I’ve been migrating a lot of older sites from old installs of Adobe Coldfusion to new servers and fresh installs of Lucee Coldfusion lately. The majority of these applications were migrated without much trouble.  I’ve found that Lucee Coldfusion is also easy to keep secure and current as it has continual stable releases and monthly patches that can be installed from the admin area.

For the most part the migration to Lucee is a simple matter of installing Lucee Coldfusion, and adding the application codebase. After thoroughly testing that the application works locally I stand up a Test server and repeat the process. After passing UAT, the test server is cloned to create the production server and the datasource is re-pointed to the production db on the new production server. Finally the DNS entry is repointed to move the web traffic from the old existing server to the new server.

Below is the process I use when starting on a new migration

  1. Stand up a Lucee dev environment
    1. I’ve been moving to Linux servers at the same time as migrating to Lucee, but for now let’s assume we’re in Windows
    2. If you’re new to Lucee, just grab the express install from Lucee.org and install it.
  2. Checkout the site’s codebase into the Lucee ROOT directory.
    1. You are using version control right?
    2. I make a new branch to track any code changes needed. If your site is simple it most likely will just work. Otherwise check this list for ideas of what might need to be changed.
    3. Alternatively you can configure it to look at a directory other than ROOT. See this blog post
    4. If you may need to set up multiple Lucee dev sites you may want to read this
    5. If you need to turn on server side authentication read this
  3. Configure any datasource your site may need in the Lucee admin area.
    1. http://YOUR_DOMAIN_NAME/lucee/admin/server.cfm
  4. While you’re in the Lucee admin area install and activate the Log Analyzer plugin.
    1. This will allow you to view the server logs much like you would in Adobe’s CFAdmin. Very handy!
  5. At this point your site may just work.
    1. If your site works, congratulations! You can begin to validate that everything really does still works
    2. If not, usually you will get an error that explains what the issue is.
    3. For more ideas of what might be wrong: Common Issues when Migrating Existing Codebases to Lucee Coldfusion.

Common Issues Migrating Existing Codebases to Lucee Coldfusion

Lately I’ve been migrating a lot of old Adobe CF sites to new Lucee installs. There’s a few differences between the two flavors of Coldfusion, but for the most part it Just Works. I’ve written the blog post below with some of the issues I’ve experienced. Hopefully this helps someone.

Have you migrated to Lucee? What issues did you find?


Does your site use Cfform Tags?

You may need to install and/or activate the Form Tag plugin through the Lucee admin area menu option  “Extensions > applications”. If you do not see this plugin available you can  download it from Lucee.org and upload it via the upload feature at the bottom of the “Extentions > applications” page.

Does your site use Cfspreadsheet?

You may need to install and/or activate the spreadsheet plugin through the Lucee admin area menu option  “Extensions > applications”. If you do not see this plugin available you can  download it from Lucee.org and upload it via the upload feature at the bottom of the “Extentions > applications” page.

Does your site generate PDFs?

The PDFs created by Lucee will be formatted differently than the ones generated by Adobe Coldfusion.  You will need to tweak the formatting to get them to work correctly.

You may need to install and/or activate the pdf plugin through the Lucee admin area menu option  “Extensions > applications”. If you do not see this plugin available you can  download it from Lucee.org and upload it via the upload feature at the bottom of the “Extentions > applications” page.

Other Issues

– Lucee Coldfusion generates JSON keys in their original case. Adobe Coldfusion generates JSON keys in uppercase. (I may have this backwards) This may be an issue if you have anything consuming JSON that is case-sensitive.

– Lucee Coldfusion does not support the Adobe Coldfusion feature called “Flash Forms”. This was a very old feature Adobe added that presented web forms using flash instead of html. Usually it is straightforward to convert these forms into normal HTML forms.

– Lucee Coldfusion does not support Coldfusion Reporting files.  I’ve only encountered this once, but it was straightforward to re-implement the report as a pdf.

– I ran into an issue where the code was dynamically generating a new Query object using the QueryNew function. Lucee’s QueryNew was counting empty list items while Adobe’s QueryNew was not.  In Coldfusion the ListLen function ignores empty list items so Lucee’s implementation seems to not follow the Coldfusion convention.

– Occasionally Lucee reveals a bug that Adobe Coldfusion allowed to pass syntax checking. I don’t have an example handy, but at the time I wondered how Adobe CF interpreted what was an obvious bug.

Creating ‘vhosts’ when setting up a Lucee dev environment

Previously when setting up a dev environment using Adobe Coldfusion I would set up multiple development sites on the same Coldfusion install using Apache vhosts. There are other ways to do this using vms or containers, but I find keeping a local dev environment as simple as possible works best for me. If the sites are all Coldfusion, I put them together in one install. (If I’m working with a different technology, then its time to set up a separate dev environment for that, just not a new environment per-site.)

Once I moved to Lucee development, I wanted to replicate the same sort of thing using Apache Tomcat. The problem I had was that Tomcat doesn’t call them “vhosts” so it took a while to Google the correct term!

The following process is how I set up multiple dev sites under one Lucee install:

Step 1)

First, we will need to edit the server.xml file.  This file is located here for me:
c:\Lucee-express\conf\server.xml
But it might also be located here: /data/lucee/tomcat/conf/server.xml
The server.xml file may be in a slightly different place for you, but its always in the conf directory.

Add the following XML inside the “<Engine>” section

<Host name="YOUR_DOMAIN_NAME" appBase="webapps"
unpackWARs="true" autoDeploy="true" >
<Context path="" docBase="PATH_TO_WEBROOT" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>

Step 2)

Update your hosts file with YOUR_DOMAIN_NAME so that your browser will point to your local server instead of going out to the internet.

To your hosts file, add the entry:

127.0.0.1 YOUR_DOMAIN_NAME

Step 3)

restart Lucee

Finished!

Go to your browser and type “http://YOUR_DOMAIN_NAME”  Lucee should respond with the content in the PATH_TO_WEBROOT directory.  You may need to add a port # if your install of Lucee is configured to run on something other than port 80. My environment is configured to use port 8888 so I would need to type “http://YOUR_DOMAIN_NAME:8888

How to Turn on Basic Server-side Authentication for Lucee

Here’s the instructions I use whenever I need to remember how to set up server-side authentication on a Lucee server. These are really instructions for Apache Tomcat, which Lucee uses as its web server.

Step 1)

Define a global “Realm” that contains the LDAP config info.

We will need to edit the server.xml file.  This file is located here for me:
c:\Lucee-express\conf\server.xml
But it might also be located here: /data/lucee/tomcat/conf/server.xml
The server.xml file may be in a slightly different place for you, but its always in the conf directory.

Add the following XML inside the “<Engine>” section

<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionURL="ldap://YOURSERVERNAME:PORT"
userSearch="(samAccountName={0})"
userSubtree="true"
userBase="YOURPARAMSGOHERE"
connectionName="USERNAME"
connectionPassword="PASSWORD"
/>

Your own AD creds should work for testing, but for production you should set up a service account to make this connection

Step 2)

Now that we have an LDAP Realm defined we need to tell the website to turn on basic authentication

Create an WEB-INF/web.xml file below your web root and stick all of the following XML in there:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>test</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.cfm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.cfm</welcome-file>
</welcome-file-list>

<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>*</role-name>
</security-role>
</web-app>

Step 3)

Restart lucee

Finished!

Now, the user will be prompted to log in to the server using their AD credentials before hitting the website. The username will be in the cgi variables if the website needs this information.

If you need to turning on LDAP logging:

Step 1)

Add
org.apache.catalina.realm.level = ALL
org.apache.catalina.realm.useParentHandlers = true
org.apache.catalina.authenticator.level = ALL
org.apache.catalina.authenticator.useParentHandlers = true

to /data/lucee/tomcat/conf/logging.properties

Step 2)

Add
debug=”99″
to the end of your Realm like this:

<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionURL="ldap://YOURSERVERNAME:PORT"
userSearch="(samAccountName={0})"
userSubtree="true"
userBase="YOURPARAMSGOHERE"
connectionName="USERNAME"
connectionPassword="PASSWORD"
debug="99"
/>

 

Sources

https://tomcat.apache.org/tomcat-8.0-doc/config/realm.html#JNDI_Directory_Realm_-_org.apache.catalina.realm.JNDIRealm
https://tomcat.apache.org/tomcat-8.0-doc/realm-howto.html#JNDIRealm
http://dev-answers.blogspot.com/2010/03/enable-debugtrace-level-logging-for.html

 

WEB-INFcftagsMETA-INFtaglib.cftld (The system cannot find the path specified)

Recently I moved a long running process inside a cfthread and began to get this error during testing: “WEB-INFcftagsMETA-INFtaglib.cftld (The system cannot find the path specified)”

The issue is that getPageContext().getServletContext().getRealPath(“/WEB-INF”) returns the incorrect path when inside a cfthread.

If you use cfthread you may eventually run into this bug, but maybe not as I think its a very rare bug. There doesn’t seem to be a fix for this issue, at least not in CF9, but I did find a workaround.

A demonstration of the bug






    
    
    

The results:

C:ColdFusion9wwwrootWEB-INF
C:wwwrootWEB-INF

Inside the cfthread Coldfusion has forgotten where /WEB-INF is!

In my case I had:


in the code inside the cfthread.
“New Query()” corresponds with the custom tag C:ColdFusion9CustomTagscomadobecoldfusionquery.cfc.
Query.cfc extends C:ColdFusion9CustomTagscomadobecoldfusionbase.cfc.

To create this object Coldfusion calls “getSupportedTagAttributes” in base.cfc which looks up the attributes in taglib.cftld. That file is located under the /WEB-INF directory. If we dig into the guts of base.cfc we find the offending code is on line 228. Coldfusion tries to find “/WEB-INF/cftags/META-INF/taglib.cftld” but since we are inside a cfthread the code fails to use the correct path.

Creating a mapping didn’t help and neither did creating a virtual directory in Apache.

The workaround

Code similar to this was working fine in the production environment, but how was it avoiding this error? The solution was found when I stepped back and read the entire function. Wrapping the offending line is the code:

if(not isdefined("server.coldfusion.serviceTagAttributes.#tagName#"))

Coldfusion will look up the attributes only if they are not already cached in server memory. This is why this bug is hardly seen: normally all these attributes have been cached before being encountered inside a cfthread. My testing was very specific and so the Query attributes were never loaded prior to entering the cfthread. The trick is to make sure the attributes are cached before entering the cfthread.

For testing I added the line:


before entering the cfthread and that forced the attributes to be cached and the error went away.

I hope this post helps someone else with this issue!

The method matches was not found in component:Ensure that the method is defined, and that it is spelled correctly.

I recently updated my local CF build to 9.0.2. After installation I reloaded my app and everything worked fine. I then went back into the admin and enabled robust exceptions and a few other things for my dev environment. I also saw an option to turn off CFC type check. I had never tried this before so I turned it on to see if there was a speed difference. Instead my app stopped loading and displayed this error:

“The method matches was not found in component C:/wwwroot/MyApp/myComponent.cfc .:Ensure that the method is defined, and that it is spelled correctly.”

Digging into the code, the issue is inside Coldspring. “Matches” is a function used by Coldspring in the ProxyFactoryBean.cfc. With CFC type check turned off it seems that Coldfusion can no longer follow the CFC inheritance and does not realize that this function exists. Turning CFC Type check back off in the CF admin solved the issue, though I am still unsure why this was a problem.

The only other info I found on this issue was this Google Groups thread.

cftag2cfscript – The cftag to cfscript converter for Coldfusion

Just uploaded my new project cftag2cfscript to github this morning.

With the arrival of Coldfusion 9 we can finally build our cfcs in cfscript. I’ve found that there can be a significant speed increase when converting an existing tag based cfc to cfscript. YMMV of course. Others may want to convert legacy cfcs to cfscript because they prefer writing in cfscript. Whatever your reason is for wanting to convert cf tags in to script cftag2cfscript is here to help.

Converting tag-based CF to script based CF is time consuming. This project aims to make it dead simple. Its not there yet, but maybe with your help we can reach that goal.

Checkout cftag2cfscript on Github