Implicit constructor and CF9 style implicit accessors without ColdFusion 9

One of the broadly welcomed features of ColdFusion 9 has been the addition of implicit getters and setters to CFCs.  What this means is that you no longer have to hand code the repetitive boiler plate getXXX() and setXXX() methods for each property in your model objects. However, you don’t need ColdFusion 9, (or even ColdFusion for that matter) to enjoy the benefits of the new implicit accessors with the version 9 release.  Since ColdFusion 8, developers have had access to the OnMissingMethod() method which makes tasks like this very simple to implement on your own.  The OnMissingMethod is also available in current versions of OpenBlueDragon and Railo.

For my implementation of this, I use a standard BaseBean class in a number of my projects which is extended by all of my model class objects.  By leveraging the OnMissingMethod() in this BaseBean, I create these implicit accessors, in addition to an implicit constructor init() method as well.

There are multiple examples on the internet that show how you can use OnMissingMethod(), but for the most part, the examples that I have come across do not protect the class from being having infinite previously undefined properties added to it from the outside.  For instance, I could have a class named Person.cfc with define properties of “firstName” and “lastName”, but nothing would stop someone from doing Person.setThisIsNotAProperty(true) and that value would be dynamically added to the Person instance. While some might argue that the flexibility that this approach offers is a positive thing, I prefer to lock my classes down just a bit more.  For instance I like the fact that I can open up a model class and see exactly what properties it can contain with clearly defined <cfproperty/> tags.   From a maintainability standpoint the idea of “mystery” dynamic properties strike me as just wrong.

For my implicit constructor, I take an approach where I loop through any named arguments that were passed, and if the name matches a property that I have defined with <cfproperty/>, then it will be passed to a setter method.  Any arguments that are passed that are not defined as a property are discarded.

So let’s take a look at what this looks like.  First I will paste the entire BaseBean, and below we will break it apart to discuss what is going on.

<cfcomponent output="false">


	<cffunction name="init" access="public" output="false" returntype="BaseBean">
		<cfset var i = "" />
		<cfset initializePropertyList() />
		<cfloop list="#this.propertyList#" index="i">
			<cfif StructKeyExists(arguments,i)>
				<cfset set(i,arguments[i]) />
			</cfif>
		</cfloop>
		<cfreturn this />
	</cffunction>


	<cffunction name="initializePropertyList" access="private" output="false" returntype="void">
		<cfset var i = "" />
		<cfif NOT StructKeyExists(this,"propertyList")>
			<cfset this.propertyList = "" />
			<cfif ArrayLen(GetMetadata(this).properties)>
				<cfloop from="1" to="#ArrayLen(GetMetadata(this).properties)#" index="i">
					<cfset this.propertyList = ListAppend(this.propertyList,GetMetadata(this).properties[i].name)>
				</cfloop>
			</cfif>
		</cfif>
		<cfreturn />
	</cffunction>



	<cffunction name="onMissingMethod" access="public" output="false" returntype="any">
		<cfargument name="missingMethodName" type="string" required="true" />
		<cfargument name="missingMethodArguments" type="struct" required="true" />

		<cfset var property = "" />

		<cfif ReFindNoCase("^[gs](et)",arguments.missingMethodName)>
			<cfset property = ReReplaceNoCase(arguments.missingMethodName,"^[gs](et)","") />
			<cfset initializePropertyList() />

			<cfif ListFindNoCase(this.propertyList,property)>
				<cfif StructIsEmpty(arguments.missingMethodArguments)>
					<cfreturn get(property) />
				<cfelse>
					<cfset set(property,arguments.missingMethodArguments[1]) />
					<cfreturn this />
				</cfif>
			<cfelse>
				<cfthrow message="The class #GetMetadata(this).name# does not have a property named #property# so the implicit #arguments.missingMethodName#() method is not available." />
			</cfif>

		</cfif>
		<cfreturn />
	</cffunction>

	<cffunction name="get" access="public" output="false" returntype="any">
		<cfargument name="property" type="string" required="true" />
		<cfset var value = "" />

		<cfset value = variables[arguments.property] />

		<cfreturn value />
	</cffunction>

	<cffunction name="set" access="public" output="false" returntype="void">
		<cfargument name="property" type="string" required="true" />
		<cfargument name="value" type="any" required="true" />

		<cfset variables[arguments.property] = arguments.value />

		<cfreturn />
	</cffunction>

</cfcomponent>

Before we walk through the actual flow, I would like to point out the method initializePropertyList() that you see here:

<cffunction name="initializePropertyList" access="private" output="false" returntype="void">
	<cfset var i = "" />
	<cfif NOT StructKeyExists(this,"propertyList")>
		<cfset this.propertyList = "" />
		<cfif ArrayLen(GetMetadata(this).properties)>
			<cfloop from="1" to="#ArrayLen(GetMetadata(this).properties)#" index="i">
				<cfset this.propertyList = ListAppend(this.propertyList,GetMetadata(this).properties[i].name)>
			</cfloop>
		</cfif>
	</cfif>
	<cfreturn />
</cffunction>

By using the GetMetadata() function, we are able to introspect our instance and create a list of property names which we can reference in our other methods.  This is what enables us to enforce the rules that I described above in which we make sure that a property exists before setting it in the constructor or through an implicit accessor.  You will see in both the init() and OnMissingMethod() methods that we call this method to ensure the list of properties is available before testing against it.

With that established, let’s take a look at the init() constructor method:

<cffunction name="init" access="public" output="false" returntype="BaseBean">
	<cfset var i = "" />
	<cfset initializePropertyList() />
	<cfloop list="#this.propertyList#" index="i">
		<cfif StructKeyExists(arguments,i)>
			<cfset set(i,arguments[i]) />
		</cfif>
	</cfloop>
	<cfreturn this />
</cffunction>

After making sure that our propertyList has been initialized, we loop through that list and if there is a matching named argument, we call the set() method which sets that value into the variables scope.

So with the object initialized, let’s take a look at our accessors.  For our example, let’s say that we have a Person object and we are doing to set our firstName property like this: person.setFirstName(“Dave”).  Since that setter method doesn’t exist in our Person class, the OnMissingMethod() below will be invoked.

<cffunction name="onMissingMethod" access="public" output="false" returntype="any">
	<cfargument name="missingMethodName" type="string" required="true" />
	<cfargument name="missingMethodArguments" type="struct" required="true" />

	<cfset var property = "" />

	<cfif ReFindNoCase("^[gs](et)",arguments.missingMethodName)>
		<cfset property = ReReplaceNoCase(arguments.missingMethodName,"^[gs](et)","") />
		<cfset initializePropertyList() />

		<cfif ListFindNoCase(this.propertyList,property)>
			<cfif StructIsEmpty(arguments.missingMethodArguments)>
				<cfreturn get(property) />
			<cfelse>
				<cfset set(property,arguments.missingMethodArguments[1]) />
				<cfreturn this />
			</cfif>
		<cfelse>
			<cfthrow message="The class #GetMetadata(this).name# does not have a property named #property# so the implicit #arguments.missingMethodName#() method is not available." />
		</cfif>

	</cfif>
	<cfreturn />
</cffunction>

We are then doing a regular expression test to see if the missing method names starts with either “get” or “set”.  If so, we derive the name of the target property by stripping the “get” or “set” off of the string.  After making sure that our propertyList has been defined, we then look in that list to see if the target property actually exists in the instance.  If it does, the request is then routed on to either the getter or the setter depending on whether arguments were passed to it.  Otherwise an exception will be thrown to let the developer know that he or she has attempted to access an undefined property.

One thing you might notice is that when our conditional block routes the request to the setter, we return an instance of the class itself.  This allows us to do method chaining like this:  person.setFirstName(“Dave”).setLastName(“Shuck”).  it should be noted that this is not the approach that Adobe took with ColdFusion 9.

So let’s take a look at it in action.  Here is our Person.cfc class.

<cfcomponent output="false" extends="BaseBean">

	<cfproperty name="id" type="string" />
	<cfproperty name="firstName" type="string" />
	<cfproperty name="lastName" type="string" />

</cfcomponent>

As you can see in the <cfcomponent/> tag, we are extending our BaseBean which is all that we need to have a workable domain class object.

When we put this together and access it in our code, we can do this:

<cfset person = CreateObject("component","Person").init(id=7,firstName="Dave", lastName="Shuck") />

<cfdump var="#person#" />

Once we have an instance, we can modify those properties like so:

<cfset person.setId(8).setFirstName("Johnny").setLastName("Rotten") />

I have not actually tested this on Railo, but I can confirm that it works in OpenBlueDragon (including GAE version), and ColdFusion versions 8 and 9.

Naked Domains in Google App Engine with GoDaddy

I recently set up a new site (hikethecanyon.org) on the Google App Engine running OpenBlueDragon.  By default when you set up a new site on GAE (Google App Engine), you choose an ID for your application, which must be unique on their system as it also serves as the hostname of the URL like this: http://[your ID].appspot.com.   For those that would like to use a different domain name, Google App Engine has mechanisms for doing so.  In the administration panel of your application, you can add a domain and then choose hostnames from that domain that the application should respond to.  However, it makes no provisions for serving the “naked domain”.

What does this mean?  For my example of hikethecanyon.org, I originally set the site up with an id of hikethecanyon-org which was initially served as http://hikethecanyon-org.appspot.com.  After adding the domain hikethecanyon.org, I was able to add the host “www” so that it would respond to http://www.hikethecanyon.org.  However, since GAE doesn’t support naked domains, I was unable to set it up to respond to http://hikethecanyon.org.  I was able find a workaround using GoDaddy’s domain forwarding functionality.  While walking fellow CFML developer Paul Kukiel through the process today, he mentioned that someone should blog this, so here it is with screenshots along the way (edit – it appears that he decided to blog it himself as well!)

For my example, I am going to use a domain I have had sitting around doing nothing for a few years (j4n.org) and walk through the process with some screenshots and explanations along the way.

First, you need to create your application in the GAE dashboard and deploy your application.  Many people have covered this topic in our community including Paul Kukiel and Aaron Lynch, so I will skip to the next step and assume that you have a running application on Google App Engine. As you can see below, I have set up an app with an ID of j4n-org that is answering on http://j4n-org.appspot.com which is just running a Mach-II skeleton application.

The next thing that we want to do is add the j4n.org domain to this application.  When you go into the GAE dashboard, you will see that option under the “Application Settings” section labeled “Domain Setup”

On this page you will see a note that tells you that the domain you add must be set up for Google Apps, a service that allows all sorts of functionality, including email services and more.  NOTE:  You do not have to use any of those services, you simply need to sign up!

By clicking the link that says Sign up for Google Apps, you will be taken to a page like this:

Walk through the process filling out your personal information and you will come to a screen that looks like this:

For our example, we are going to choose to create a new CNAME record in DNS to prove to Google that we own the domain.  By choosing that option

At this point we need to go to the GoDaddy DNS manager and create a host name google46353a9a2d07a035 and point it to google.com.  You can see what that looks like below:

Once that record is in place we can go back to the Google Apps page and click the button labeled I’ve completed the steps above.  If all goes well, you will see a page directing you through additional setup.  For our purposes in this example, we are done with Google Apps for the time being.  Now we want to go back to the GAE dashboard and tell it that we want to use the j4n.org domain.

When you enter that domain you should see a message that looks like this:

This will bring us back into the Google Apps control panel for the j4n.org domain and we can add hostnames to our application like this:

When you click add you will see an page like the one below instructing you to add another CNAME to GoDaddy for the host “www”.

In the screen below you will see that we have successfully added the “www” host and while we were in there I went ahead and deleted the temporary CNAME that we had to create earlier to validate the ownership of the domain.

At this point we can actually reach our application with the address http://www.j4n.org as you see below:

While this is pretty cool and all, we still can’t access our application with http://j4n.org.  For this, we will count on GoDaddy to do the rest.  Go back into the GoDaddy domain manager look for this link:

On the next page, you will want to fill out the field like you see before.  However, before you do, click the “learn more” link in the bottom left corner.  On that page there is a very important note:  For your domain to forward, your domain’s A record must be

64.202.189.170

. If you note my DNS information above, that is not what the default parked domain IP is.  I won’t bore you with yet another screen shot, but make sure you alter your domain’s A record.  Now when we ping j4n.org we get a response from 64.202.189.170.

Once we enter in www.j4n.org you can see that our plan is going to work by hitting the “Preview” link to the right and seeing a snapshot of our app!

You will notice that we accepted the default settings which actually does a 301 redirect from http://j4n.org to http://www.j4n.org.  This means that we will never actually see http://j4n.org in the address bar after the page has loaded.  If you click on the advanced settings you can select “masking” which allows the url to remain in the address bar as http://j4n.org.  Each option has its own advantages.  Select what is right for your application and choose OK.

That is all you need to do!  Now, a word of warning… we have all gotten spoiled by the seemingly instant DNS changes in recent years.  You will find that when you make this forwarding change, you may need to wait up to half an hour or so before you can see the finished product (your mileage may vary).

Relaunched HikeTheCanyon.org on OpenBD and GAE

Around a year or so ago, I inadvertently took hikethecanyon.org offline in a server move.  Considering that it is a very low traffic site that is little more than a scrapbook of hiking pictures and descriptions, there is no active user community to send me nasty messages begging for me to bring it back online.  Finally this past weekend, I spent a bit of time and revived the code base off an old server, moved all the images out to Amazon S3 and brought the site up running under OpenBlueDragon on the Google App Engine.  Other than a very rudimentary Lightbox drop-in I did on the gallery to replace a no-longer functioning Flash image gallery, I didn’t actually touch the codebase or the design.  So if it looks dated to you, that is because it is!

For those interested in hiking, you may want to give it a look.  It documents a hike of the Grand Canyon that I took with my dad in 2005 with a very detailed trip report and over 300 pictures.  Enjoy!

HikeTheCanyon.org – Rim-to-Rim through the Grand Canyon on North Kaibab and the Bright Angel Trail

Setting up Apache, OpenBD, Railo and ColdFusion – Part 3 – Installing ColdFusion and customizing the connector

This is the third part in a series of posts on setting up ColdFusion, OpenBlueDragon, and Railo all on the same machine using Apache webserver to listen for all requests and direct traffic.  Part 2 can be found here.  You will find links to all parts of this series at the bottom under “Related Content”

With that said, this part in the series focuses on installing ColdFusion and configuring the webserver adapter in such a way that only specific Virtual Hosts will be set up to pass requests to the ColdFusion server. First we want to start by creating a localhost site that is specific to ColdFusion 8 in Apache.  I tend to keep all my sites under /www which is actually symlinked to a ‘www’ in my home directory. I find a few benefits in this.  First, I usually keep my home partition in shape and carry it around with me from distro to distro, so I always have my sites in tact with me.  Secondly since it is a symlink to my home and not in a system folder I don’t need special permissions to write in it.  I will be following along this path, but if you keep your sites elsewhere, then you can adjust as necessary.

$ mkdir /www/localhost.cf8

Now, we will want to create an Apache virtual host definition for this site.  To do so, create a new configuration file like this:

$ sudo gedit /etc/apache2/sites-available/localhost.cf8

Paste the the following, then save and close.

<VirtualHost *>
	ServerName localhost.cf8

	<Directory /www/localhost.cf8/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride None
		Order allow,deny
		allow from all
	</Directory>
	DocumentRoot /www/localhost.cf8
</VirtualHost>

Now we need to make sure that file is included when Apache starts, so run the following command which will make a symlink to the sites-enabled directory.

$  sudo a2ensite localhost.cf8
Site localhost.cf8 installed; run /etc/init.d/apache2 reload to enable.

As you can see from the localhost.cf8 configuration file, we are expecting our ServerName to be localhost.cf8, so we now need to add that entry to our hosts file.

$ sudo gedit /etc/hosts

Append “localhost.cf8″ (with no quotes!) to the line that begins with 127.0.0.1.  Save the file and close. At this point you should be able to restart Apache and hit that empty site in your browser like this: Now that we have a site ready, it is time for us to install ColdFusion.  Once you have downloaded the .bin installation file from Adobe, browse to that directory in a terminal window.  You may need to chmod the file to be executable, then launch it like this:

$ chmod +x coldfusion-801-lin.bin
 sudo ./coldfusion-801-lin.bin

Choose 1 for English.  After the welcome screen, hit enter to continue.  Next type “Y” and hit enter to agree to the terms and conditions. We are now faced with the installation type prompt. For this example of setting up a development environment, we will choose option 3 “Developer Edition” For our purposes we are going to choose the “Server configuration” option.  However, it should be noted that you could quite easily choole the J2EE WAR file option and install into Tomcat as we did with OpenBlueDragon in Part 2 of thise series. Since we are installing from scratch, we will choose “No” (2) on the next option which is asking if there is an existing version of ColdFusion 8 installed on this machine. For this installation we do not want any of the extra options to install such as Documentation, LiveCycle, Search Services, nor do we want to start on system init since this is on my laptop and I may not always want ColdFusion to start at boot.  So we will uncheck all options like you see in this image and continue. We are going to accept the default installation path of /opt/coldfusion8 Again, since this is a fresh installation, we are going to say “No” (2) to the prompt asking if there are earlier versions of ColdFusion on this computer. Now we start to work our way into the webserver configuration which will tie ColdFusion into Apache.  To start, choose “Add Web Server Configuration” (1) when prompted, then choose “Apache” (1).  In the following prompt asking for the Apache directory that contains your http.conf file, enter /etc/apache2 as you see in the picture below: For the location of the Apache program binary file, enter /usr/sbin/apache2.  For the Start/Stop script, enter /etc/init.d/apache2.  You will see both of these choices here: We now return to the first webserver configuration menu and this time choose “Continue with installation” (4). Then we will need to enter the location of the webroot.  We are going to enter the directory of our new site /www/localhost.cf8 that we created above as you can see in the picture below.  We will also be asked which user we would like ColdFusion to run as.  I typically like to use my own user account for this so I don’t end up with permissions issues where I have difficulty accessing files generated by ColdFusion Now enter your admin password, and if you choose to user RDS, enter the  password for it as well. It will now show you the general options you have selected and you will hit enter to start the actual installation.  Once it completes and prompts you to “Press Enter to exit the installer”, do so and then start the server with this:

$ sudo /opt/coldfusion8/bin/coldfusion start

During this stage you should see messages that it is configuring the webserver successfully, assuming we entered everything properly above.  Once you are returned to a prompt, it is time to go customize the Apache connector stuff just a bit.  open the httpd.conf file like this:

$ sudo gedit /etc/apache2/httpd.conf

In that you will find the connector stuff that ColdFusion added starting with a line: #JRun Settings. Before we take the next steps, let me explain a bit what we are going to do.  We are going to seperate this into two pieces: the module loader, and the actual connector declaration.  As it stands right now, and request coming through the webserver would be handled by ColdFusion and we don’t really want that.  To make it more granular, we are going to create an include file that can be added to any site that will add the connector only to that particular site.  With that said, let’s walk through it.   *Cut* (not copy!) these two lines of that connector info:

# JRun Settings
LoadModule jrun_module /opt/coldfusion8/runtime/lib/wsconfig/1/mod_jrun22.so

Now we are going to paste those into a new file that will go in our mods-available directory.  Click on the “New” button in gedit and paste that text in.  Now save that file as  /etc/apache2/mods-available/cf8.load. Now *cut* (not copy!) the remainder of the connector out that looks like this:

<IfModule mod_jrun22.c>
    JRunConfig Verbose false
    JRunConfig Apialloc false
    JRunConfig Ignoresuffixmap false
    JRunConfig Serverstore /opt/coldfusion8/runtime/lib/wsconfig/1/jrunserver.store
    JRunConfig Bootstrap 127.0.0.1:51801
    #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>

Create a new file named /etc/apache2/cf8connector. Pasted that text in and save the file. Lastly, you may not have this issue, but I found that the DirectoryIndex attribute of Apache was not adding index.cfm to the list of default files. Due to this I actually added it to my httpd.conf. After all of the steps above, my httpd.conf file only has a single line:

DirectoryIndex index.cfm

Now… it is time to do just a little more Apache config and we are ready to go!  Rember that cf8.load mod file we created earlier?  Let’s turn that on:

$ sudo a2enmod cf8

Now, let’s to add an include call to our localhost.cf8 virtual host configuration.  Open up /etc/apache2/sites-available/localhost.cf8 and add the “Include c8connector” line that you see below:

<VirtualHost *>
        ServerName localhost.cf8

        <Directory /www/localhost.cf8/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>
        DocumentRoot /www/localhost.cf8
        Include cf8connector
</VirtualHost>

Once you have saved that file, it is time to restart Apache and test out all of our hard work!

$ sudo /etc/init.d/apache2 restart

Now, using your browser, go to http://localhost.cf8/CFIDE/administrator/ and you will see the following: Now… if you are following along from earlier in this series, you should now be able to successfully connect to OpenBD at http://localhost.bd and ColdFusion 8 at http://localhost.cf8 On the next part of this series, we will bring Railo into the mix and finally have all three running on our system.

Setting up Apache, OpenBD, Railo and ColdFusion – Part 2 – Installing Tomcat/Apache/OpenBD

This is the second part in a series of posts on setting up ColdFusion, OpenBlueDragon, and Railo all on the same machine using Apache webserver to listen for all requests and direct traffic.  Part 1 can be found here

Remember, the steps below have some commands specific to Linux, and more specifically to Debian/Ubuntu, but the concepts in general should have at least some similarites across any supported platform, especially you Mac folks.

To start out, we need to make sure that we have the Apache webserver installed with optional “dev” package.  Additionally, later on we will need to be compiling, so let’s make sure that you have the build-essential package as well

$sudo apt-get install apache2 apache2-threaded-dev build-essential

Next I installed the Sun Java 6 JDK

$sudo apt-get install sun-java6-jdk

Next you want to go download Tomcat.  I chose to use Tomcat 6, specifically v. 6.0.18, which the current release as of this posting.  Now, using a terminal cd into the directory where you saved the dowloaded file and do the following:

$ sudo cp apache-tomcat-6.0.18.tar.gz /opt/
$ cd /opt
$ sudo tar xvzf apache-tomcat-6.0.18.tar.gz
$ sudo mv apache-tomcat-6.0.18 tomcat6
$ sudo rm apache-tomcat-6.0.18.tar.gz

Next we will need to edit the Tomcat startup script, but to do so, we need to go get a little information first.  We need to ensure that we know what the current Java home is on your machine.  There are surely easier ways of accomplishing this, but here is the series of steps I took.

~$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 2009-01-30 23:00 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java[return] lrwxrwxrwx 1 root root 36 2009-01-30 23:00 /etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java 

From that last line I can see that the default Java lives at /usr/lib/jvm/java-6-sun/ (which too is a sym link, but that’s ok!). Now that we have our Java home we can edit the Tomcat startup script

$sudo gedit /opt/tomcat6/bin/catalina.sh

Paste the following lines in just after the big comment block at the top. Make sure that if your Java path looked different than mine did, you will want to adjust accordingly.

JAVA_HOME=/usr/lib/jvm/java-6-sun
JRE_HOME=/usr/lib/jvm/java-6-sun/jre
JAVA_OPTS="-server -Xms1024M -Xmx1024M -XX:PermSize=256m -XX:MaxPermSize=256m 
    -Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8 
    -Djavax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl" 	

Now we want to download the Apache Tomcat connector source so that we can pass requests from Apache webserver to Tomcat. This is the one I grabbed: http://apache.org/dist/tomcat/tomcat-connectors/jk/source/ Next you will want to browse to the directory that you downloaded that file into using in the terminal. Next run:

$ tar xvzf tomcat-connectors-current-src.tar.gz
$ cd tomcat-connectors-1.2.27-src/native
$ ./configure --with-apxs=/usr/bin/apxs2
$ make
$ sudo make install

Now we will need to create a jk mod file to be included by Apache so that it loads the adapter when Apache starts. In your terminal cd to /etc/apache2/mods-available. In this directory we will create a file named jk.load.

$sudo gedit jk.load

In that file pasted the following, then save and exit:

LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
# Where to find workers.properties
# Update this path to match your conf directory location (put workers.properties next to httpd.conf)
JkWorkersFile /etc/apache2/workers.properties
# Where to put jk shared memory
# Update this path to match your local state directory or logs directory
JkShmFile     /var/log/apache2/mod_jk.shm
# Where to put jk logs
# Update this path to match your logs directory location (put mod_jk.log next to access_log)
JkLogFile     /var/log/apache2/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] "

Now we want to create a symbolic link to this file in /etc/apache2/mods-enabled so that it is loaded when Apache starts.

$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/jk.load ./jk.load 

Next we want to create a virtual host in Apache to catch the requests. We are going to create a new file in the sites-available directory.

$ cd /etc/apache2/sites-available
$ sudo gedit localhost.bd 

In that file, paste the following, save, and exit:

<VirtualHost *>
	ServerName localhost.bd
	JKMount /* worker1
</VirtualHost>

Now we need to create a symbolic link to that file from sites-enabled so that it is available when apache2 starts.

$ cd /etc/apache2/sites-enabled
$ sudo ln -s ../sites-available/localhost.bd ./001-localhost.bd

Next we want to make sure that we can get to that site in a browser, so we are going to add ‘localhost.bd’ to our hosts file. Open up /etc/hosts, and append ‘localhost.bd’ (without quotes!) to the line that begins with 127.0.0.1. Now we need to define that “worker1″ that we just referenced above in the VirtualHost definition. We will do that by creating a workers.properties file in our apache2 directory.

$ cd /etc/apache2
$ sudo gedit workers.properties

Insert the following. Then save and exit:

# Define 1 real worker using ajp13
worker.list=worker1
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost.bd
worker.worker1.port=8009  

Next we want to create a webapp in Tomcat for Apache to send to.

sudo gedit /opt/tomcat6/conf/server.xml

In that config, we need to define the localhost.bd site, or ‘webapp’. Add the following:

<Host name="localhost.bd"  appBase="webapps"
      unpackWARs="true" autoDeploy="true"
      xmlValidation="true" xmlNamespaceAware="false">
	<Context path="" docBase="localhost.bd/" reloadable="true" privileged="true" antiResourceLocking="false" anitJARLocking="false">
	</Context>
</Host>

Now we need to create the local.bd directory under Tomcat. Note: as you get more comfortable and adventurous, you may want this to be a symbolic link to another place on your machine where your source resides, but for now we are keeping it as simple as we can. Once the directory is created, we will download the OpenBlueDragon war file and extract it.

$ sudo mkdir /opt/tomcat6/webapps/localhost.bd
$ cd /opt/tomcat6/webapps/localhost.bd
$ sudo wget http://openbd.viviotech.net/downloader.cfm/id/64/file/openbd.war
$ sudo jar xvf openbd.war 

And with that step, and after restarting Apache, and starting Tomcat, OpenBlueDragon will now be available.

$ sudo /etc/init.d/apache2 restart
$ /opt/tomcat6/bin/catalina.sh start

Open up your browser and go to: http://localhost.bd/bluedragon/administrator

You should be created with your OpenBD admin page like this:

Setting up Apache, OpenBD, Railo and ColdFusion – Part 4 – Installing Railo under Tomcat with Apache webserver

This is Part 4 in an ongoing series demonstrating how to install OpenBlueDragon, ColdFusion, and Railo concurrently with all requests passing through the Apache webserver.  You will find links to all parts of this series at the bottom under “Related Content”

In this post we will be building upon our existing environment in which we installed Apache webserver, Tomcat 6, OpenBlueDragon, and ColdFusion, by adding Railo to the mix.  If you have been following along thus far, we are well past the hard stuff at this point.  To install Railo, which is deployed as a java war file, we are going to repeat and slightly modify many of the steps that we took at the end of Part 2 when we installed OpenBD as a Tomcat web application.

Let’s start by setting up our hosts entry so that our new site resolves to localhost.railo, and set up the Apache webserver to listen for the request.  Open up /etc/hosts, and append ‘localhost.railo’ (without quotes!) to the line that begins with 127.0.0.1.   Next we want to create a new virtual host file for the site under Apache.  Do so like this:

$ cd /etc/apache2/sites-available
 sudo gedit localhost.railo

Paste the following into that new file and save it.

<VirtualHost *>
	ServerName localhost.railo
	JKMount /* worker1
</VirtualHost>

As we learned in Part 2, the line “JKMount /* worker1″ is instructing apache to pass everything to the worker we defined in /etc/apache2/workers.properties.  That worker will then pass the request on to Tomcat port 8009, under which our application actually resides.

Now that we have defined this site, we want to make sure that it gets included on our next Apache restart.  We do this by running the following:

$ sudo a2ensite localhost.railo
Site localhost.railo installed; run /etc/init.d/apache2 reload to enable.

At this point, we need to make sure there is a an application set up in Tomcat to receive our request.  First, let’s start by downloadingthe free Railo Server from their download page.  Look toward the bottom of the page and download  “Railo Custom” and download railo-3.0.2.001.war. (or newer version if it is there).  Once we have the file downloaded, we will create a new directory for our application under Tomcat.  We will then copy the Railo war file into it from our download directory.  When we have the war file under /opt/tomcat6/webappas/localhost.railo/ we will extract it, and then safely delete the war file itself.  These steps can be seen here:

$ sudo /opt/tomcat6/webapps/localhost.railo
 sudo cp railo-3.0.2.001.war /opt/tomcat6/webapps/localhost.railo/
 cd /opt/tomcat6/webapps/localhost.railo
 sudo jar xvf railo-3.0.2.001.war
 sudo rm railo-3.0.2.001.war

Since we now have the application in place, it is time to modify the Tomcat server config so that it knows to send the appropriate requests to it.  Do the following:

$ sudo gedit /opt/tomcat6/conf/server.xml

Look for the section that we added previously for our OpenBlueDragon localhost site “localhost.bd”.  We are going to copy that section, modifying the “name” and “docBase” attributes to match our new application and paste it just below the localhost.bd site.  When you are done they should look like this:

<Host name="localhost.bd"  appBase="webapps" unpackWARs="true"
	autoDeploy="true" xmlValidation="true" xmlNamespaceAware="false">
	<Context path="" docBase="localhost.bd/" reloadable="true" privileged="true" antiResourceLocking="false" anitJARLocking="false" />
</Host>

<Host name="localhost.railo"  appBase="webapps"  unpackWARs="true"
	autoDeploy="true" xmlValidation="true" xmlNamespaceAware="false">
	<Context path="" docBase="localhost.railo/" reloadable="true" privileged="true" antiResourceLocking="false" anitJARLocking="false" />
</Host>

With all that done, we are ready to restart (or start) Apache, Tomcat and our new Railo site will be available at http://localhost.railo

So with our original goal of being able to run the three CFML engines, it’s time to see how we did….
http://dl.getdropbox.com/u/101948/blog/movies/3-cfml-engines.swf