Yeah, but does it run on [ENTER YOUR CF SERVER HERE] ?

Thursday, November 6, 2008

Configuration for Testing Adobe ColdFusion, Railo, and Open Blue Dragon using Apache Virtual Hosts and MXUnit and Ant It may be redundant to say, but testing becomes more challenging as the number of platforms you have to support grows. So, what if you want to move your CFML apps to another engine or you want your apps to work on all engines? How do you do it? Well, duh, test it!

I'm going to describe a couple of things: (1) How I set up my environment for testing, and (2) how I leverage MXUnit and Ant to perform concurrent tests on each platform.

There's a number of different approaches to this problem (VWMare or VirtualBox come to mind). This particular method is not so sophisticated but should be portable to various virtual images targeted to be run on different OSs.

The following should allow any developer on any platform with a couple of hours to be able to put together something that allows him or her to test their application on ColdFusion, Railo, and Open Blue Dragon. And it won't cost you anything but some bandwidth, and hopefully the headache was mine.

The napkin design ...

mxunit-qa440

For the app I want to test (MXUnit, natually), I want each CFML server to point to the same set of files on disk. I don't want to have different versions of the app in different web roots. Think a about that - I would have test in one server, then copy to another, test there, copy to the other, and round and round trying to keep track of changes... eek! Another thing I want is the URLs I use to test my apps be descriptive and simple: http://adobe, http://railo, http://obd. Lastly, I want the ability to run my tests on each platform concurrently.

These are the general steps: 1. Download and install server software 2. Decide on a web root location 3. Edit your hosts file 4. Connect your CFML Engines to Apache 5. Create Apache Virtual Hosts 6. Configure your CFML Engines 7. Run Smoke Test 8. Build and Run Ant based MXUnit tests

1. Download and install server software: 1. Apache 2.2 2. Adobe ColdFusion 8 (Multi-instance) 3. Railo Server /Resin 4. Open Blue Dragon - Jetty/Ready2Run

I won't bore your with talk about installing these products, as most are well documented.

At this point you have Apache running on localhost:80, a ColdFusion instance on localhost:8301, Railo on localhost:8600, and Open Blue Dragon on localhost:8080. Don't worry if your ports are not the same, just as long as they don't conflict with one another, you should be ok.

2. Decide on a web root location. I use D:/webapps on Windows or /home/billy/webapps on Ubuntu

3. Edit your hosts file On Windows this should be in C:\Windows\system32\drivers\etc\hosts, Unix /etc/hosts.

On Windows it may only have one entry: 127.0.0.1 localhost

Add the following:

127.0.0.1 railo 127.0.0.1 adobe 127.0.0.1 obd

This tells your machine to resolve the names to your localhost address, 127.0.0.1.

4. Connect your CFML Engines to Apache

4a. Adobe: Adobe ColdFusion has the webserver connector tool, which does the work for you. This should be located in {CF-Install}/bin/wsconfig.exe. Check the Adobe documentation for details.

This will make some entries in {Apache}/conf/http.conf See below.

4b. Railo - Open up the {Apache}/conf/http.conf file and add the following at the bottom.

#Load Railo Module LoadModule caucho_module "{Railo-Install}/win32/apache-2.2/mod_caucho.dll"

Where {Railo-Install} is the full path to your installation; e.g. LoadModule caucho_module "C:/railo-3.0.0.005-resin-3.1.2-with-jre-windows/win32/apache-2.2/mod_caucho.dll"

4c. Open Blue Dragon - OBD does not have a web server connector, but you will need to do some URL re-writing in the virtual host config - a whopping 2 lines of code! See next section #5.

The bottom of my httpd.conf looks like this:

##########################################################
#
# Load CFML Engine Plugins
#
##########################################################

# JRun Settings
LoadModule jrun_module "C:/JRun4/lib/wsconfig/1/mod_jrun22.so"
<IfModule mod_jrun22.c>
JRunConfig Verbose true
JRunConfig Apialloc true
JRunConfig Ignoresuffixmap false
JRunConfig Serverstore "C:/JRun4/lib/wsconfig/1/jrunserver.store"
JRunConfig Bootstrap 127.0.0.1:51000
#JRunConfig Errorurl url <optionally redirect to this URL on errors>
#JRunConfig ProxyRetryInterval 600 <number of seconds to wait before trying to reconnect to unreachable clustered server>
#JRunConfig ConnectTimeout 15 <number of seconds to wait on a socket connect to a jrun server>
#JRunConfig RecvTimeout 300 <number of seconds to wait on a socket receive to a jrun server>
#JRunConfig SendTimeout 15 <number of seconds to wait on a socket send to a jrun server>
AddHandler jrun-handler .jsp .jws .cfm .cfml .cfc .cfr .cfswf

</IfModule>

#Load Railo Module
LoadModule caucho_module "C:/railo-3.0.0.005-resin-3.1.2-with-jre-windows/win32/apache-2.2/mod_caucho.dll"

Note: Make sure the mod_rewrite and mod_vhost_alias module lines are uncommented (top of file). These are needed to create virtual hosts and to do the URL rewriting for Open Blue Dragon 5. Configure Apache Virtual Hosts Each virtual host entry represents a unique host url I want to invoke for each CFML server.
#Make any requests for http://adobe get processed by the Adobe CFML engine

<VirtualHost adobe:80>
ServerName adobe
ServerAlias adobe
DocumentRoot "D:/webapps/"

<Directory "D:/webapps/">
Order allow,deny
Allow from all
Options Indexes SymLinksIfOwnerMatch
DirectoryIndex index.html index.cfm
</Directory>
</VirtualHost>



#Make any requests for http://railo get processed by the Railo engine

<VirtualHost railo:80>
ServerName railo
ServerAlias railo
DocumentRoot "D:/webapps/"

<Directory "D:/webapps/">
Order allow,deny
Allow from all
Options Indexes SymLinksIfOwnerMatch
DirectoryIndex index.html index.cfm
</Directory>

ResinConfigServer railo 6800

</VirtualHost>



<VirtualHost obd:80>
ServerName obd
ServerAlias obd
DocumentRoot "D:/webapps"

RewriteEngine     On
RewriteRule       ^(.*)$       http://localhost:8080$1  [P]


<Directory  "D:/webapps/">
Order allow,deny
Allow from all
Options Indexes SymLinksIfOwnerMatch
DirectoryIndex index.html index.cfm
</Directory>
</VirtualHost>
######################################################
#            End httpd-vhosts.conf
######################################################

Notes:

Each virtual host correlates to a host name in my hosts file. So, when the web browser requests http://adobe, my machine forwards that to Apache on port 80. Apache is configured, by default, to use Adobe ColdFusion to process any CFML file. Next, if I request http://railo, again, my machine forwards the request to Apache, but, this time Apache has the instruction to process ResinConfigServer railo 6800. This tells caucho_module to process requests on the server named "railo" (localhost) on port 6800. This is the port Resin is listening on. All results are sent back to Apache and then web browser.

Also note that the Document Root for all these virtual hosts is the same, d:/webapps.

6. Configure CFML Server

Open Blue Dragon

1. Since ODB does not have web connector, we will use Apache's URL rewriting capabilities. In the above, any request made to http://obd will be processed by http://localhost:8080, which is where OpenBlueDragon and Jetty are running.

2. You will also need to edit the jetty.xml configuration file to specify the common webroot. This is located in C:\jetty-6.1.12-OpenBD\etc\jetty.xml. In this file we have to tell Jetty about our d:/webapps. Find the <Set name="handler"> elements and add the following above the <New id="cfmlWebContext_1" class="org.mortbay.jetty.webapp.WebAppContext">...</New> element. Note that the cfmlWebContext_1 element points to a sample Open Blue Dragon app with a couple of CFML pages. You should be able to keep that there.

<Item>
<New id="mxunit_qa" class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">D:/webapps/</Set>
<Set name="defaultsDescriptor">
<SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
<Set name="VirtualHosts">
<Array type="java.lang.String">
<Item>127.0.0.1</Item>
<Item>localhost</Item>
</Array>
</Set>
</New>
</Item>

Railo

In the Railo web administrator (http://localhost:8600/railo-context/admin/web.cfm), under Archives & Resources, create a Mapping. For the Virtual value enter a "/" and for the Resource value, enter D:\webapps. The primary should be Resource and I'm not sure what trusted does, but I left that unchecked.

ColdFusion

Nothing special is apparently needed. If you run into an issue you could create a mapping in the ColdFusion Administrator for "/" pointing to D:\webapps. But this was not needed for me.

7. Run A Simple Smoke Test

Now, you should be able to start all these servers and they should all be running. When developing I always start my servers from the command line. That way, I can watch for debug output to stdout instead of digging through log files.

C:\> C:\apache\Apache2.2\bin\httpd.exe C:\> C:\Jrun4\bin\jrun start dev C:\> C:\railo-3.0.0.005-resin-3.1.2-with-jre-windows\httpd.exe C:\jetty-6.1.12-OpenBD\> java -jar start.jar

A Quick Visual Inspection: Here's a basic web page with an iframe for each virtual host. Formatting HTML omitted. <iframe src="http://adobe/mxunit"></iframe> <iframe src="http://railo/mxunit"></iframe> <iframe src="http://obd/mxunit"></iframe>

qa-matrix

Naturally, I'm using MXUnit, but this would apply to any app you want to test. Again, the goal is to have a common webroot for all CFML servers.

8. Build and Run MXUnit Ant-based tests

Now here's where the real power comes in! I totally heart Ant's <parallel> task and would buy it a lobster dinner if I could.

At this point you can run your tests anyway you please - open a web browser, er eh, and click each page one at a time and visually compare results. But what if you could do this really really fast? How about running 100 or more tests on each server at the same time? And be able to repeat it? Enter Ant and MXUnit ... Details on the MXUnit Ant task can be found here and the Test Automation section here.

Luis Majano's ColdBox Framework has been reporting some issues with MXUnit when run on Railo. In order to help find these pesky critters, I set up an Ant build to run Luis's tests on Railo and Adobe at the same time.

<project name="MXUnitTask" basedir="." default="runtests">

<property name="mxunit.jar" value="ant/lib/mxunit-ant.jar" />
<taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunit.jar}"   />

<property name="test.dir" value="D:\webapps\coldbox\testing\tests\cases\beans" />
<property name="component.path" value="coldbox.testing.tests.cases.beans" />

<property name="output.dir" value="tmp" />

<target name="runtests" description="Run same tests on all servers concurrently">

<taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunit.jar}"   />

<parallel>

<!-- run Adobe Tests -->
<mxunittask server="adobe" port="80"
outputdir="${output.dir}/adobe"
defaultrunner="/mxunit/runner/HttpAntRunner.cfc"
verbose="true"
haltonfailure="false"
haltonerror="false">

<directory runner="/mxunit/runner/HttpAntRunner.cfc"
     remoteMethod="run"
     path="${test.dir}"
     packageName="adobe.${component.path}"
     componentPath="${component.path}"
     recurse="true"/>

</mxunittask>

<!-- run Railo Tests -->
<mxunittask server="railo" port="80"
outputdir="${output.dir}/railo"
defaultrunner="/mxunit/runner/HttpAntRunner.cfc"
verbose="true"
haltonfailure="false"
haltonerror="false">

<directory runner="/mxunit/runner/HttpAntRunner.cfc"
 remoteMethod="run"
 path="${test.dir}"
 packageName="railo.${component.path}"
 componentPath="${component.path}"
 recurse="true"
/>
</mxunittask>
</parallel>

</target>

</project>

Take note of parallel, which spawns a separate thread for each sub-task. This effectively cuts this test's time in half!

Tip: It's also possible to speed up any testing effort simply by leveraging the the parallel task but point the mxunit ant task to different directories.

Using the junitreport task (not displayed here), I can then print a report. I particularly like this one - 168 tests, 0 Failures, 0 Errors. No critters found here, but they may be lurking somewhere.

Happy testing,

bill


References:

Setting up Railo and Apache on Unix

Setting Up Railo and Apache on Windows

Open Blue Dragon

MXUnit

ColdFusion

Apache Ant

6 comments:

Jim Collins said...
This comment has been removed by the author.
Jim Collins said...

How did you get the napkin design?

Mike said...

if you're looking for something to do napkin designs, take a look at balsamiq

billy said...

@Jim,
I hope this old-skooler doesn't disappoint:

1. Get a piece of paper; preferably, a dry white cocktail napkin which can be found in most restaurants, pubs or coffee bars.

2. Borrow a pen from someone else. This is a critical step! Not having a pen forces you to be more urgent with your ideas and gives you the appearance of someone slightly insane.

3. Unfold the napkin and place it on a dry area with creases pointing up so that the napkin doesn't curl up over your design.

4. Articulate your ideas in a broad scope, using boxes and lines. I've found getting too detailed too quickly makes me forget stuff and order more to drink sooner.

5. When done, make sure the ink is dry. Waive the design in the air and blow on it to make sure it can withstand packaging (see next).

6. Carefully, fold the napkin and place it in front pocket of jeans or jacket pocket with a snap or zipper.

7. Now, order something else to drink and reflect on your brilliance. It's especially nice when going through this process with a colleague!

Notes: Beer, coffee, or other beverages can ruin the design. Practice good security constraints with your napkin and insure it remains dry. If you forget to return the borrowed pen, keep it with your design and lavishly acknowledge the pen lender when your project hits the ground.

bill

mrt181 said...
This comment has been removed by the author.
mrt181 said...

only the first virtual host is executed. if i put rail first, all sites, are served through railo even with this url http://adobe/somesite/.
When i put adobe before railo than all sites are served through coldfusion (http://railo/somesite/)