In my last post I mentioned that I had been toying around with using Tomcat as the only servlet container to deploy all my ColdFusion applications to, regardless of what ColdFusion engine you needed to use for a specific project. My goal in trying to get this working was actually 3-fold:
- Learn more about how standard JEE servlet containers worked and how to configure them
- Remove my dependence on JRun as it is not under active development any more
- Be able to have one central place to start/stop each application’s instance as I switch between client projects
So far, I’m 2 for 3 on those goals. What follows is a brief history of what I did in the current iteration, what works well and what I’m still missing to have what I believe is the perfect development environment (at least for my situation). The steps I took here are based on my experiments using Mac OS X, but should be fairly close for Windows users.
The first thing I did was download Apache Tomcat 6 and extract it to /opt/tomcat (any directory will do, that’s just where I wanted it).
At the moment, my Mac uses Java 1.5 as its default JVM (as determined by typing “java -version” into a terminal window). I wanted Tomcat (and by extension, my CF instances) to run on Java 1.6 so I added the following line to
/opt/tomcat/bin/catalina.sh just below the large comment block at the top:
The only thing required to start Tomcat is to change to the /opt/tomcat/bin directory and type:
At this point, you should be able to open a browser and type http://localhost:8080 and see the Tomcat welcome page. This forms the basis of the various attempts that I made to get this set up the way I wanted (and more than once I blew away my /opt/tomcat directory and started afresh).
Host name resolution
Before you can start browsing your site, you’ll need to edit your hosts file (/etc/hosts on OS X, c:\windows\system32\drivers\etc\hosts on Windows) so that the URL you want to use resolves to your local machine. I’m embarrassed to admit how many times I forget this step.
Configuring Tomcat to serve your files
The next step I took was to configure a virtual host in Tomcat’s server.xml file (server.xml is located in the /conf directory under your main Tomcat directory). This tells Tomcat to listen for requests on a particular URL (eg sitename.local). Change the file paths below to match the location of the files that you want to serve.
<Host name="siteName.local" appBase="/Users/userName/Sites/Client/com.projectname.www/" autoDeploy="false" unpackWARs="false" deployOnStartup = "false"> <Context path="" docBase="/Users/userName/Sites/Client/com.projectname.www/html/" /> </Host>
An important note here is that the appBase value should be one directory level higher than the docBase specified in the Context element. As of Tomcat 6, the documentation suggests alternative ways to specifying the Context element rather than including it in the server.xml. Their reasoning is that including it here requires you to restart Tomcat if there are any changes to the contexts. In my case, since this is my local development machine, that’s not an issue, so I chose to do things the easy way and include it here.
Once this is done, you should be able to browse that same static HTML or image file by using the URL
Apache Web Server Setup
I’m going to assume that you already have your web files configured to be served by the Apache web server and can browse to a static HTML or image file using a local URL (eg. http://siteName.local). In order to be able to browse to your site without specifying the 8080 port number, you have to configure a connection from Apache web server to the Tomcat virtual host we just set up. To do this, I’m using a module for Apache called mod_jk. To get this module loaded by Apache at startup, I added the following code to my httpd.conf file (change the paths to the .so file if needed–mod_jk.dll is the Windows equivalent). Make sure the log directory already exists.
# Load mod_jk module LoadModule jk_module /usr/libexec/apache2/mod_jk.so # Where to find workers.properties JkWorkersFile /usr/local/apache2/conf/workers.properties # Where to put jk shared memory JkShmFile /var/log/httpd/mod_jk.shm # Where to put jk logs JkLogFile /var/log/httpd/mod_jk.log # Set the jk log level [debug/error/info] JkLogLevel info # Select the timestamp log format JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories -ForwardLocalAddress
You’ll notice that the line that starts “JkWorkersFile” specifies a file named workers.properties file that gets loaded. This file is what tells mod_jk how to connect to the Tomcat server ports.
# Define workers using ajp13 worker.list=siteName # Set properties for workers worker.localhost.type=ajp13 worker.localhost.host=siteName.local worker.localhost.port=8009
There’s one more thing we need to do to enable our Apache web server to talk to Tomcat. We need to tell our Apache virtual host what files to send to Tomcat. This is done inside our virtual host block for
JkMount /*.cfm siteName JkMount /*.cfc siteName
So at this point, we have Apache configured to talk to Tomcat. We also have Tomcat configured to look at the directories where our web files are. However, we haven’t given Tomcat any information on how to handle our ColdFusion requests. The last thing we need to do is to put the contents of the WAR file for our preferred ColdFusion engine (eg Railo).
Configuring Tomcat to Serve ColdFusion Files
This part seems to me to be kind of a hack to me, but it works. I take the Railo (for example) WAR file and drop it into my tomcat/webapps directory. Tomcat will auto deploy and expand the WAR into its own directory. I then grab the files that were auto expanded and copy them to my Apache web root.
I mentioned that this setup gets me 2 out of 3 of my goals. The only thing that this doesn’t do is give me a central spot to start and stop Tomcat virtual hosts. If you have several projects configured as I do, when you start Tomcat, it automatically starts all those CFML engine instances which can be a drag on your system resources. If anyone has a way around this particular pitfall, I’d LOVE to hear about it.
Hopefully this will help someone. I spent a bunch of hours researching and experimenting with various configurations. In the end, I not only have a stable development environment, but I’ve learned quite a lot on how JEE servers are configured and behave.