Monday, August 30, 2010

2010 Packt Publishing Open Source Awards

Packt Publishing has announced their 2010 Open Source Awards. This is the fifth year for the awards, which started life as the Open Source CMS Awards, so I strongly encourage everyone to participate by voting for your favorite open source applications.

The current phase of the awards is the nominations phase, and you can see all the categories and make your nominations here. Nominations are open until September 17, then voting runs September 27 - November 5, and the winners are announced on November 15.

Particularly in the CMS category CFML can make a really strong showing if as many people as possible nominate Mura as best Open Source CMS. I've used a lot of CMSes in my time and in my opinion Mura stands right up there with better-known solutions such as Drupal or Joomla, so let's get Mura on everyone's radar!

For more information about the 2010 Open Source Awards you can visit the web site or read the full press release here.

Saturday, August 28, 2010

Accessing a Network Drive from Apache and Tomcat on Windows Server

A few quick tips if you find yourself having to access a network drive from Apache and Tomcat on a Windows Server. This is all pretty much old hat but since I still get questions about this fairly regularly and was just setting up some things on some servers this weekend, I figured I'd write this up.

In my situation we're running an application on three VMs behind a load balancer, and users can upload files from the application. Since I didn't want to set up a process behind the scenes that copied uploaded files between all three servers (though it would have given me a chance to take another run at using Unison), we have an uploads directory living on a SAN. This way no matter which VM the user is on, the uploads all go to and are served from a single file system.

On Windows Server, by default services run under the Local System Account, which doesn't have access to network resources. So if you install Apache and Tomcat as services and expect to be able to point them to a UNC path for some of your content, that won't work out of the box. You need to be running Apache and Tomcat under an account that has network access. In most environments in which I've worked this type of account is typically called a "service account," because you'll end up getting a domain account just like your typical Active Directory user account, but of course it won't be associated with a human being.

Once you have that account in place, you go into your services panel, right click on the service, click on "Properties," and then click the "Log On" tab. You'll see by default the Local System Account radio button will be checked. Click the radio button next to "This Account," enter your service account information, click "OK," and then restart the service. At this point your service will be running under the service account and will have access to network resources. Note that you'll have to do this for each service that needs access to the network drive, which in my case meant doing this for both Apache and Tomcat.

That takes care of the web server and things at the Tomcat level in terms of basic access, but you'll likely be configuring an alias of some sort to point to the network drive. In my case I wanted /uploads to point to \serversharenameuploads, which meant setting up an alias in Apache, a Context in Tomcat, and a mapping in OpenBD. This is where a lot of people get confused, so I'll go through each of these settings one by one.

The necessity for a web server alias is probably pretty obvious. If you're serving an image directly from your web server, e.g. http://server/uploads/image.gif, if /uploads doesn't exist under your virtual host's docroot, then Apache will throw a 404.

Allowing Apache to access the network drive involves (depending on how you have Apache configured) using a Directory directive to give Apache permission to access the directory, and then an Alias directive so Apache knows where to go when someone requests something under /uploads. So the following goes in your virtual host configuration file:

<Directory "\serversharenameuploads">
  Order allow,deny
  Allow from all

Alias /uploads "\serversharenameuploads"

You may have other stuff in your Directory directive as well but that's the basics of what will allow Apache to see /uploads as the appropriate location on your SAN.

The next layer down will be your CFML engine. Remember that if in your CFML code you want to read or write files to /uploads, even though Apache knows what that is now, your CFML engine will not. I'm emphasizing that point because it's such a common source of confusion for people. If things are happening in your CFML code, it won't be interacting with Apache at all, so it won't know about the Alias you set up in Apache. Simple enough to solve with a mapping; just go into your CFML engine's admin console and create a mapping that points /uploads to \serversharenameuploads and that handles things at the CFML level.

Lastly comes Tomcat. Depending on how you're serving files, you may be proxying from Apache to Tomcat, so if Tomcat needs to know where /uploads lives, since it's not in the webapp's base directory Tomcat will throw a 404 unless you tell it where /uploads is located.

Tomcat doesn't have Aliases in the same way Apache does, but what you can do in Tomcat is configure multiple Contexts under a single host. So in Tomcat's server.xml (or in a separate host config file if you prefer), you simply add a Context that points /uploads to the network location:

<Host name="myapp">
  <Context path="" docBase="C:/location/of/my/app" />
  <Context path="/uploads" docBase="\serversharenameuploads" />

So now you have things set up in such a way that Apache, your CFML engine, and Tomcat all know where /uploads really lives.

Another point of confusion for people on Windows is the concept of "mapped drive" letters. A lot of people think that if you map \serversharename to a drive letter of let's say D:, than in your code you can then access the uploads directory we've been using as our example via D:uploads.

The simplest way to explain why this doesn't work is to point out that mapped drive letters are associated with a Windows user account. They don't exist at the operating system level. While you may remote into the server using your credentials, map to a network location, and assign that to drive letter D:, another user logging in won't see that mapping, and services running on the server under various user accounts definitely won't know anything about mapped drives.

This is why in all the examples above you see the full UNC path to the network resource being used. You have to use the UNC path in order to get this all to work correctly because that's the only way services running under a service account will be able to address the network resource.

Hope this helps eliminate some of the persistent confusion I see around this issue.

Friday, August 20, 2010

Quick Apache/Tomcat Proxying Tip

I'm setting up some new servers with some semi-complex URL rewriting and proxying going on of both the HTTP and AJP varieties. For this particular application the home page is actually a completely separate application that's running as its own webapp on Tomcat, and everything else runs from within the webapp itself. (I'll spare you the details; just assume I'm not insane and this was the best way to handle this situation.)

So for all this to work properly I have the following rewrite rule:

RewriteRule ^/$ http://otherapp/ [NC,P]
ProxyPassReverse / http://otherapp/

Then below that I have a bunch of AJP rewrites for the webapp itself. What was throwing me fits was that everything was working great except for this one rewrite rule, which would attempt to load indefinitely until I killed the request.

I stared at my virtual host config file for quite a while and finally paused on this line:

ProxyPreserveHost On

Given that the ^/$ rewrite rule is proxying out to a different host, it seems kind of obvious now that of course that would confuse Apache. Removing that line and adding some aliases for the other host's CSS and images directory did the trick.

Maybe no one else will be in this exact situation, but if you're ever faced with a blank white screen while waiting forever for an HTTP proxy to go through, this tip might come in handy.

Thursday, August 19, 2010

Get Your Hands Dirty at BFusion/BFlex

BFusion/BFlex is coming up on September 11 and 12, 2010 in lovely Bloomington, IN. You need to be there, and here's why.
  • $30 for one day or $45 for both days is one of the best deals you'll find in the conference world. (No, I'm not missing a zero at the end of those prices!)
  • BFusion/BFlex is all hands on, all the time. This isn't a passive event by any stretch. You come armed with your laptop and you get to learn from the best people in the business.
  • Multiple all-day classes in both CFML and Flex are available. On the CFML side you can learn Mach-II from the great minds behind it (namely Peter Farrell and Kurt Wiersma), you can learn CFML from scratch from the great Adobe instructor Matt Boles, if you're a programmer already but want to learn CFML you have none other than Simon Free at your disposal, and if you're an open source junkie like me or just want to learn more about the free CFML engines, I'm giving an all-day in-depth class on that.
  • Great for all skill levels, from pure beginner up to advanced developers. There's literally something here for everyone so you don't have an excuse not to come. Just check the BFusion and BFlex schedules and tell me you don't see something interesting!
  • It's a nice intimate environment where you can corner speakers or other attendees and get whatever help you need.
  • Indiana University is a great venue with great facilities. Power and Internet for all!
  • Bloomington is a great town with tons to do.
I've been invovled with BFlex/BFusion since the first year and it's one of my favorite conferences. I'm particularly excited this year to be able to help people delve into the open source CFML engines, so I hope to see lots of you there.

Great training, great price, great location, and great people. What are you waiting for? GO REGISTER NOW!

Wednesday, August 18, 2010

Senior CF Job in Washington, DC

Job details below--contact for additional information.


Computer Programmer IV

Systems Integration & Development Inc., an IT solutions provider located in Rockville, Maryland is currently seeking a Computer Programmer IV to perform programming services. The successful candidate will have experience with developing web-based applications using ColdFusion, Javascript, and SQL, and Oracle databases. This is a full-time position located in Washington DC. US CITIZENSHIP IS REQUIRED. Roles and responsibilities include:

  • Performs programming services, converts specifications (precise descriptions) about business or scientific problems into a sequence of detailed instructions to solve problems by electronic data processing (EDP) equipment, i.e. digital computers; draws program flow charts to describe the processing of data, and develops the precise steps and processing logic which, when entered into the computer in coded language (COBOL, FORTRAN, or other programming language) to cause the manipulation of data to achieve desired results.
  • Tests and corrects programs, prepares instructions for operators who control the computer during runs, modifies programs to increase operating efficiency or to respond to changes in work processes, and maintains records to document program development and revisions.
  • Applies expertise in programming procedures to complex programs; recommends the redesign of programs, investigates and analyzes feasibility and program requirements, and develops programming specifications.
  • Plans the full range of programming actions to produce several interrelated but different products from numerous and diverse data elements, which are usually from different sources; solves difficult programming problems, and uses knowledge of pertinent system software, computer equipment, work processes, regulations, and management practices.
  • Develops, modifies, and maintains complex programs; designs and implements the interrelations of files and records within programs which will effectively fit into the overall design of the project; works with problems or concepts and develops programs for the solution to major scientific computational problems requiring the analysis and development of logical or mathematical descriptions of functions to be programmed; develops occasional special programs, e.g. a critical path analysis program to assist in managing a special project.
  • Tests, documents, and writes operating instructions for all work, confers with other EDP personnel to secure information, investigate and resolve problems, and coordinates work efforts.
  • Performs such programming analyses as: investigating the feasibility of alternate program design approaches to determine the best balanced solution, e.g., one that will best satisfy immediate user needs, facilitate subsequent modification, and conserve resources.
  • Assists user personnel in defining problems or needs, determining work organization on typical maintenance projects and smaller scale, working on limited new projects, the necessary files and records, and their interrelation with the program or working on large or more complicated projects, and participating as a team member along with other EDP personnel and users, holding responsibility for a portion of the project.
  • Works independently under overall objectives and direction, apprising the supervisor about progress and unusual complications and modifying and adapting precedent solutions and proven approaches. May function as team leader or supervise a few lower level programmers or technicians on assigned work.
  • Bachelor’s degree in Computer Science or a relevant computer-related field or 8 years equivalent experience.
  • At least 6 years of experience with the design, code, and maintenance of complex web-based applications using Adobe ColdFusion, JavaScript, and complex SQL queries.

Thursday, August 12, 2010

Eliminating index.cfm From Mura URLs With Apache and mod_rewrite

This may seem like it's a topic that's been beaten to death since there are several examples of how to do this, but none of the examples I found quite fit my exact situation. And since URL rewrite rules are all about getting the exact right characters in the exact right order (pesky computers), I thought I'd share my situation in the hopes of saving someone else some time.

First, in case some of you aren't using Mura but are reading out of general interest in URL rewriting (get a life! ;-), let's take a look at Mura URLs. Mura URLs are in the format http://server/siteid, where 'siteid' is an actual physical directory on disk. Since Mura is built on CFML it uses a directory index file of index.cfm, so when you hit http://server/siteid it's the equivalent of hitting http://server/siteid/index.cfm. The presence of a .cfm file is what triggers Apache to hand off the processing of that file to the CFML engine. This is rudimentary stuff I realize, but that index.cfm bit is important in this case since that's what we're going to be eliminating from the URL.

Pages other than the site index page in a Mura site have URLs along the lines of http://server/siteid/index.cfm/page-name, and the 'page-name' bit is not a directory or file on disk since all the Mura content is contained in the database. So if my site ID is 'foo' and my page name is 'bar', the URL for the 'bar' page would be http://server/foo/index.cfm/bar What I'd like my URL to be for that page, however, is http://server/foo/bar, so I want to eliminate index.cfm from the URL.

The solution for this is to use URL rewriting in your web server, which in my case is Apache and mod_rewrite. Using URL rewriting I can have the web server match certain URL patterns and translate these patterns into something different behind the scenes so things still work properly. So in this case I need a rewrite rule that will take the URL http://server/foo/bar and treat that as if it were http://server/foo/index.cfm/bar. Otherwise, Apache would be looking for a directory 'bar' under the 'foo' directory, which of course doesn't exist, so it would throw a 404.

Many of the URL rewrite examples I came across were designed for Mura sites that are also eliminating the site ID from the URL. This is all well and good, but since I'm working on an intranet site we want to keep the site IDs in the URLs (e.g. http://server/department), so that meant most of the examples I saw weren't quite right for my needs.

The tricky part (at least for me as a relative mod_rewrite amateur) is that instead of being able to say "take my server name, add 'index.cfm' to that, and then tack on the rest of the URL being requested," I had to take the first part of the URL being requested (the site ID, which again is a physical directory), then insert index.cfm, then tack on the rest of the URL being requested (i.e. everything after the site ID in the URL).

This is actually pretty easy if you want to create a rewrite rule for each site ID on the server, but that would mean additional Apache configuration and an Apache restart every time a new site is added to Mura. That seemed like a maintenance nightmare to me so I decided to try to come up with a solution that would handle eliminating index.cfm regardless of the site ID.

What I ended up doing was cobbling together several of the other great resources linked above for many of the other considerations with rewriting for Mura, and then came up with a rewrite rule that will leave the site ID in place, then add index.cfm, and then tack on the rest of the URL being requested.
Quite a lot of preamble for a one-line rewrite rule, but here it is in all its gory glory:

RewriteRule ^/([a-zA-Z0-9-]{1,})/(.*)$ ajp://%{HTTP_HOST}:8009/$1/index.cfm/$2 [NE,P]


  • Create a backreference match for alphanumeric characters and hyphens in the URL up to the first / (these are the allowed characters in Mura site IDs)
  • Create a second backreference for everything else in the URL
  • Proxy this to port 8009 on the server (since I'm using AJP proxying with Tomcat), but make the URL backreference 1 + /index.cfm/ + backreference 2
The backreference stuff wound up being my savior here. Basically whatever you put in parens in the regex of your rewrite rule becomes a backreference, so whatever matches that pattern gets assigned to a placeholder. That way when you want to do the rewriting you can refer to pieces of your URL using $ and the position. So in this case $1 refers to the first backreference (the Mura site ID), and $2 refers to the second backreference (everything in the URL following the site ID).

There are a few other rewrite rules involved to get this all working when you take into account things like image files, etc., and as I said above I'm standing on the shoulders of giants (thanks guys!), so here's the full set of rewrite rules:

  ProxyRequests Off

  <Proxy *>
    Order deny,allow
    Allow from

  ProxyPreserveHost On
  ProxyPassReverse / ajp://your-host-here:8009/

  RewriteEngine On

  # if it's a cfml request, proxy to tomcat
  RewriteRule ^([cm])(/.*)?$ ajp://%{HTTP_HOST}:8009$1$2 [P]
  # if it's a trailing slash and a real directory, append index.cfm and proxy
  RewriteRule ^(.+/)$ ajp://%{HTTP_HOST}:8009%{REQUEST_URI}index.cfm [P]

  # if it's a real file and haven't proxied, just serve it
  RewriteRule . - [L]

  # require trailing slash at this point if otherwise valid CMS url
  RewriteRule ^([a-zA-Z0-9/-]+[^/])$ $1/ [R=301,L]

  # valid cms url path is proxied to tomcat
  RewriteRule ^/([a-zA-Z0-9-]{1,})/(.*)$ ajp://%{HTTP_HOST}:8009/$1/index.cfm/$2 [NE,P]

Note that you can put the rewrite rules in a .htaccess file or in the virtual host configuration file. I prefer having the rewrite rules be defined as part of the virtual host, so in my case I have all this in the <VirtualHost> block in my virtual hosts config file. (I have a bunch of other stuff in the virtual host configuration as well but I left everything other than the parts relevant to the URL rewriting out to avoid any confusion.)

That's it! I hope that helps others looking into doing this with Mura, or that you at least learned a few things about mod_rewrite along the way.

Friday, August 6, 2010

Nicholas Negroponte: The Physical Book Is Dead In 5 Years

Today at the Techonomy conference in Lake Tahoe, CA, CNBC’s Maria Bartiromo sat down with a panel including Bill Joy, Kevin Kelly, Nicholas Negroponte, and 
Willie Smits. The topic was basically the future of technology. And Negroponte had the most interesting (or at least the most controversial) thing to say.

The physical book is dead, according to Negroponte. He said he realizes that’s going to be hard for a lot of people to accept. But you just have to think about film and music. In the 1980s, the writing was on the wall that physical film was going to die, even though companies like Kodak were in denial. He then asked people to think about their youth with music. It was all physical then. Now everything has changed.

The biggest issue with this, and not that I dispute it's happening, is the tremendous potential for abuse of control of access to books. We all should have seen this coming, but when makes a deal with a large publisher that their books will only be available on the Kindle ( it's rather scary to follow that pattern to its logical end.

Unless we figure out how to address the rise of e-books from the standpoint of public libraries, this is absolutely horrible for society at large. If Amazon controls some books, you better believe Barnes & Noble, Sony, Apple, and other e-reader vendors are looking at doing the same thing.

People shouldn't have to have four different e-book readers to have access to all the books available in the world. And what about those who can't afford *any* e-book readers? Are they just out of luck?

Every time I go to my local library I'm always excited to see all the people there, particularly parents with young children who can't get enough of reading. If this all changes because greedy corporations make exclusive deals with all the world's publishers, we as a society have failed in a huge, huge way, and we'll absolutely have a day of reckoning at some point in the not-too-distant future.

Sunday, August 1, 2010

My CFFree Presentation from Dallas TechFest

Dallas TechFest was last Friday and although I was sad to be missing the final CFUnited, TechFest was a blast. It was incredibly refreshing to see 400+ CFML, PHP, .NET, Java, and Flex people all in the same place at the same time for some geek cross-pollination. This doesn't happen nearly enough so thanks to all the organizers of the event, all the great speakers, and to Dave Shuck for inviting me to speak.

The talk I gave was entitled "CFFree: Building and Deploying CFML Applications on a Free Software Stack." This was a 90-minute introduction to developing, deploying, testing, and monitoring CFML applications using Tomcat, Open BlueDragon, Railo, and a plethora of other free software applications and tools.

If you didn't make Dallas TechFest this year and are interested in this topic you're in luck! I gave everyone who attended my session a VirtualBox VM that has all the free CFML goodness installed on Ubuntu 10.04, and you can download the VM from my Dropbox (2.5 GB).

You can also view the presentation directly in Google Docs; just make sure to click "Actions" at the bottom then "Show Speaker Notes" to view the speaker notes since the slides alone don't tell you all that much.

As always if you grab the VM or read through the presentation and have any questions about any of this feel free to contact me. I'm considering doing a couple of screencasts on this topic because due to time constraints I had to breeze over some of the configuration details, not to mention some of the free software goodness I didn't get to show at all.

If you want to learn more about free CFML in person, next up on the calendar is a full day hands-on session that Adam Haskell and I will be doing at BFusion in September, and then of course three full days at OpenCF Summit in February 2011. Hope to see you at one or both of these events!