Call for Contributors

Okay, here's the scoop. I make no secret that I consider myself to be pretty competent... In fact a number of people over the years have come to the conclusion that I'm downright conceited. :) On the other end of the spectrum a CF user group manager in Florida once in response to the question "who here has worked with x" at which I was the only person to respond said "well obviously, because Ike's done everything". I took it as a complement.

The reality is I'm just one guy and no one person, no matter how smart or how little they sleep can possibly know everything there is to know about ColdFusion, much less software in general. That being the case, I've always had a vision of the onTap framework being host to an array of plugin applications that operate as "services" to one another, creating a powerful software synergy between open-source projects and commercial products provided by entirely different people.

You would use the onTap framework as a foundation and then you would install the Members onTap plugin for managing your user information, onContact for contact information (my own commercial app), and then you would buy and install a CMS from some other vendor and a shopping cart from yet someone else. And all these applications would work together without requiring any tweaking or integration on your part. All the integration would be done for you by the framework!

Does that sound really cool? Well there's a name for it, it's called a Service Oriented Architecture (SOA) and it's something Sean Corfield has talked about a fair amount recently. Much of the underlying structure for this already exists ... in fact, most of it has been in the framework for a long time. The recently released Version 3.2 of the framework merely simplifies the management of these services and improves performance.

However! I don't know everything. I recently realized that I was somewhat behind the curve on caching techniques and I blogged at the time about starting a new project called CacheBox, which I plan to include in upcoming releases and hope will be used by other frameworks as well. And although I've had several people tell me already that they're interested in this new project, it's currently on hold. Why? Because Rob Brooks-Bilson is giving a presentation at the Adobe Max conference about advanced caching techniques for ColdFusion and I want to get his notes and pick his brain some before I make much more progress on that project (although I won't be at Max).

And herein lies the problem. I'm just one guy. I can't know it all! And I can't do it all! I've got loads of things I want to do, many that I've wanted to do for a long time, and just not enough hours in the day to do them. I need some help to make these projects fly. I've actually wanted more people to be involved in the onTap framework and contributing for a long time -- years in fact, since I started working on it. I honestly don't know why there aren't more people using it. There are probably a variety of reasons, but there's been very little feedback.

So this is my public admission that "I SUCK AT MARKETING" and at the same time an open request for more people to contribute.

So how can you get involved?

There are several ways you can contribute to the onTap framework.

  • Make Suggestions: Simplest thing you can do. Is there something you've always wanted to be able to do with CF and haven't been able to figure it out? Email me and I'll see what I can do. And if I can't find a project that does it and I can't do anything about it myself, then I'll blog about it and we'll see if the community can provide a solution!
  • Write about it: You can download it, check it out and write a blog about your experiences, good or bad, BOTH HELP! If you've tried it and had a bad experience, write a blog about it and shoot me an email. It may very well be that you had issues with something I myself didn't like and have since improved - OR - if not then I may be willing to work on whatever issue you're having. The worst case scenario is that we disagree about how to write software, in which case we can agree to disagree... but you won't know until you ask. :)
  • Documentation: If there's anything you don't understand about the framework, or would like to understand better, just ask. If I've omitted anything in the documentation or if there's anything that could be better explained, I'm more than happy to update the documentation, and would love to include your articles or examples as well if you'd like to write them, it would help me out tremendously. :)
  • Review / Contribute Code: Look over my code and see what you find. If you can improve it -- performance, better functionality, better security, whatever, send me your revisions and I'll see about including it in an upcoming release. Even if it's just comments in the code - I know a lot of my code doesn't have a lot of comments. If you're scratching your head, ask, I don't bite. :) And we can add comments wherever they might be useful.
  • Write Plugins: DataFaucet is a good example of this. The DataFaucet ORM framework includes an onTap framework plugin in its distribution. What's it do? Not much -- all it does is act as a facade for integrating the DataFaucet ORM with the onTap framework. The installer may be a little involved, but guess how big the guts of it are? TWO files... yes, two. Not two-hundred, not twenty, TWO. Beyond that, the rest of the plugin is the installer... the installer is actually much larger than the plugin itself! What I'm really getting at here is that creating a plugin for the onTap framework is really easy to do and you may even already have a project or application that would work well as a service like DataFaucet or as a sub-application. Do you like Transfer? Would you rather use Transfer than DataFaucet? Write a Transfer plugin! I'm sure Mark would love to include it in his Transfer distribution and And of course, if you have any questions about how to write the plugin or the installer, just ask, I'm happy to help!

I'm looking forward to working with you!

ike

Version 3.2 Released

I just finished the 3.2 release version of the onTap framework with a variety of new enhancements that make it much more flexible than before.

Moreover particularly thanks to application-specific mappings in ColdFusion 8, this new version finally makes good on my long-time goal of a Service Oriented Architecture (SOA) for ColdFusion.

To my knowledge this is the only framework that allows plugin-style sub-applications that can be installed via a browser with no programming required, in the same way that you might install Eclipse plugins for example or Firefox extensions. I eventually hope to update the plugin manager to host a discovery service for finding, downloading and installing new plugins directly within the framework, similar to the way both Firefox and Eclipse have features to let you "get extensions".

The framework's IoC Manager is the final piece of the puzzle, giving you simple, built-in access to all your application's installed plugins, sub-applications or general services.

Want to know if a particular service is available?

request.tap.getIoC().containsBean("serviceName")

What if that service is part of someone else's plugin and you don't know if it's been installed?

request.tap.getIoC().containsBean("serivceName","pluginName")

Want to create a webservice that uses someone else's plugin to deliver data?

<cfcomponent displayname="myWebservice" extends="cfc.ontap">

<cfset variables.plugin = getIoC().getContainer("plugin") />

<cffunction name="doSomething" access="remote" output="false">
<cfargument name="argx" type="string" />

<cfreturn plugin.getBean("thingManager").useIt(argx) />
</cffunction>
</cfcomponent>

OnTap: a service oriented approach to ColdFusion development.

UPDATE Aug-4: Of course, it's always immediately following publishing a release that you notice some simple oversight! Turns out the readme files for all four projects were chocked full of references to http://www.fusiontap.com - the domain I no longer own... so I had to update them all to point to http://ontap.riaforge.org as the official site. And republish the archives ... and re-tag them in SVN. :)

IoC and Lazy Libraries

Okay, so I'm finally going to post something actually related to the framework again. :)

Here's the deal. I've been aware for a while that folks have been unhappy with some of the features in the onTap framework, in particular the fact that there are a number of places where code is executed outside of CFCs. This is done in the framework for very specific reasons, and I know for a fact that it's actually more flexible than using CFCs (think "Fusebox lexicon" and you should start to get an idea why). I also believe (although I don't know) that it's not significantly more "dangerous" (see my articles about duck-typing and about descriptive variable names).

Still it's difficult for people (myself included) to see past their knee-jerk responses to something that looks unusual or seems like a bad practice to actually understand the problems it solves.

So in recent weeks, largely because I was already migrating the ORM components out to DataFaucet, I started making some pretty radical changes to the onTap framework. This is good news on several fronts. First if you're already using it, you don't need to worry, because the system was so well encapsulated already (believe it or not, yes, yes it was), that your code shouldn't change by more than a handful of lines. In spite of the fact that I'm taking a few weeks to make these changes, *your* changes shouldn't take more than a few minutes. Secondly the new system is adding CFCs in some critical places and in at least one place this will make the system much more tweakable. It's certainly going to improve on its already very effective encapsulation.

First, the _appsettings.cfm that has confused people for a long long time as the initial method of configuring the framework is going away. It's being replaced by a config.cfc in the application root directory that extends tap.cfc which loads the framework core. This leads to some simplifications of some previous features like application-specific mappings. Want another mapping? Simple.

<cfcomponent displayname="config" extends="tap">

<cffunction name="configure" access="private" output="false">

<cfset addMapping("datafaucet","../datafaucet") />

</cffunction>
</cfcomponent>

Is that a relative path?! In a mapping? Yes it is... and it works. the addMapping() method allows you to specify mappings either absolute or relative to the framework root directory. How does it know? If it finds a directory on the relative path, then it's relative, otherwise it's absolute. Also the addMapping() function automatically prepends the required "/" at the beginning of the mapping string, which has been the source of LOTS of confusion about how precisely to create mappings in ColdFusion 8. Which means this method of adding mappings is much simpler and more straightforward than Application.cfc.

The code for path-settings is also going to become CFCs and there will be a similar, new _mappings directory for the addition of 3rd-party mappings (which should be used sparingly, but will be an important enhancement to the framework's plugin manager).

Now on to the 2 features I mentioned in the article title. I've already added lazy-libraries. In the past the framework has had a bit of a heavy initial load because it loaded its entire set of function libraries on application start. Going all the way back to the ColdFusion 5 days there had been this notion of having a library of functions (DLL wouldn't be an entirely bad analogy), which each understood their own dependencies and could then load those dependencies when they themselves loaded.

Sweet! At least in theory. In practice however loading them always turned out to be a pain. When / where do you load them? Which ones need to load on app start? Which ones can be deferred? Have I loaded x on a given page request? Should I load it on request start? ::sigh:: leading me ultimately to make the framework load them all by default, which was ugly and had some of its own problems aside from the initial load time.

A while back I had this notion of creating a "lazy loading" library out of them, where all those functions before had been in a simple structure, they would become part of a CFC and then could be loaded dynamically as-needed using the new onMissingMethod() feature in ColdFusion 8. I had actually even started working on that change a while ago and ended up giving up and rolling the change back in SVN because I had too many problems implementing it at the time. Well now I've gone back and revisited the idea and I've managed to overcome all the challenges I found before. :)

Sweet! So now you never have to worry about whether or not a particular function is loaded because the library will load it for you when it needs it. And there's an extra bonus that the framework loads faster! I've also added internal references in the libraries themselves so that instead of calling request.tapi.OtherMethod() the internal method calls become lib.OtherMethod() -- using the internal pointer. Granted that if you're calling a method in the same library, it can just use this.OtherMethod() -- lib.OtherMethod() just allows you to traverse the library from the root (similar to the way the default / mapping in ColdFusion lets you traverse files from the web root).

The core onTap.cfc also got a new getLib() method for returning the framework's core library, so that library calls from CFCs can be "composed" rather than referencing the request scope directly.

The only down side to this change is that due to a limitation in the getCurrentTemplatePath() method caused by inconsistency in its behavior (which the CF team last I knew refused to acknowledge), the file methods had to be moved outside of the main library to a new request.fs. structure. Those functions can't be stored in a CFC -- no way, no how. There simply is no workaround that allows them to exist in a CFC. Unfortunately... I believe I've also added getFS() to the ontap.cfc to fetch the file library in the same way that the core library is "composed". This way if at some point in the future it becomes possible to move that library back into the lazy library, then getFS() can just return the getLib() pointer and the getFS() method can be deprecated. So that should be good forward-looking.

If you're using the file.cfc to manage your files, then you don't have anything to worry about with this change. You might need to do a little extra leg-work if you were calling a lot of request.tapi.fileRead() or the like -- you'll just have to change those references, which shouldn't be too difficult.

Lastly I haven't started working on it yet, but I'm planning an IOC-MANAGER for the next release. I say "manager" because although it will have a default IOC package, the system is going to be designed specifically for the purpose of managing multiple IOC packages from different applications / plugins. So where for example ColdBox has just an IOC-type (coldspring/lightwire) to integrate a single IOC configuration, the onTap framework will instead have an addIOC() method for attaching arbitrary IOC packages, and a facade for allowing you to write your own IOC-wrappers (although I plan to include one for ColdSpring and one for LightWire out of the box). Your application code can then either getIOCManager().getBean("name","DataFaucet") for example or it can getIOCManager().getIOCPackage("DataFaucet").getBean("name"). Although I would encurage not doing those all in the same function and instead compose separate getIOCManager(), getIOCPackage() and getIOCBean() functions in your own components. That will minimize the amount of code you need to write later if anything in the core application needs to change - OR - if you later decide to migrate to a different framework.

This Looks Like a Job for EventDuck!

So if you've worked with some other frameworks and you're curious about the onTap framework, it occurs to me that there's a reasonably simple way to convert your views to use the onTap framework without removing any of the references they make to the "event" object, even though the onTap framework doesn't have one and generally uses the "attributes" scope like older versions of Fusebox.

Just download the enclosure in this blog and extract it to the root of your onTap framework application (apologies to anyone who tried to download it before, I didn't realize you wouldn't be able to download a .cfc as an enclosure)

The .cfm in the archive will execute prior to your "event-handler" code (which is placed in /_local/) for each event and instantiate the duck, creating a substitute for the event object of your favorite framework.

I think this should work for views ported from ColdBox, Fusebox or Mach-II. Model-Glue might be a bit more involved with the viewState object, but the principal should be the same. The only reason this might break in any of your views is if either I didn't include an event method you use frequently in your views* or you've got a view template that calls methods on another CFC and those methods are strict-typed, expecting the "event" object to be of type "ColdBox.system.event" or the like instead of having an argument type of "any". But then in theory there shouldn't be a lot of method calls in your view templates anyway. ;) Still, it's another good reason to duck type.

* do people use param in their views? add a comment or drop me a note and I'll add any methods you use if I can simulate them

Inversion of Control (IoC)

Okay, so I realize that a lot of folks are gonna expect me to trash some venerable object-oriented programming (OOP) design pattern. I suspect I'm fairly growing a reputation for it if I haven't already. But actually this blog is going to be a little different.

I've been working on the Galleon project recently and originally I wasn't going to install ColdSpring, but I discovered that it's actually a requirement for the latest release of Model-Glue. In the process of doing the research, in spite of the fact that I haven't been converting any of Ray's code to use any IoC frameworks, I've seen some things that I hadn't seen before. And I can understand why some folks would value having an IoC framework in spite of the fact that I'm still not entirely sold on them personally.

I may even be convinced to create an IoC component in the onTap framework core release as a facade that would be capable of providing access to any given 3rd-party IoC framework (ColdSpring, Lightwire, etc.). From the outside it would look similar to the ColdBox IoC plugin -- meaning that's how your code would interact with it, although the internal code would be designed with an eye toward supporting more than just ColdSpring or Lightwire and may even provide some of its own functionality on top.

Mostly I just wonder how much of a selling point this would be? Would it really turn people on to the idea of trying the onTap framework if I added an IoC facade?

Another Galleon Update

Okay, so writing the report is taking a bit longer than I'd like it to take. ;)

And it's not just because I'm trying to make it more accessible by offering explanations of MVC terms like "what the heck is a controller?"

A lot of it boils down to the "cheat sheets" aspect of the report. What I know from experience is that ColdFusion frameworks in particular tend to have the same set of "features" or at least techniques for doing things. For example all these frameworks offer some method of redirecting the browser to a new page. The trick is that even though they might be doing exactly the same thing "under the hood", the syntax for it varies from one framework to the next -- and usually really only by name.

So for example in traditional Fusebox you've got the <relocate url="index.cfm"> verb - but if you transition to nuveau Fusebox (no xml) then this becomes a method call of myFusebox.relocate(url="index.cfm") in your controller CFC and moving to ColdBox changes the name again to Event.setNextEvent("eventName","query=string"). If on the other hand you transition to Mach-II, then you'll be sticking with XML and the tag becomes <redirect url="index.cfm"> (instead of relocate). Fusebox and Mach-II both offer their own custom features in those tags (Fusebox XFA - Mach-II module/event), but if all you want to do is redirect the browser you can easily translate your application back and forth between traditional XML-Fusebox and Mach-II just by changing the name of the tag from "relocate" to "redirect" and vice-versa.

And that really is the crux of it. Once you've learned a given framework (any framework), you should have a decent basic understanding of the fundamentals of how they work that will translate pretty well to most other frameworks. So much of this article is tied up in showing code samples across the different frameworks in such a fashion that you really could just read through the article and then have an understanding of how you could take what you have in one and with a few multi-file replacements reasonably have a mostly working copy of the same application in another framework. And that should be the end-of-the-line for anyone who's still indecisive about choosing a framework.

And that's even becoming more true over time. As I've been going through the documentation for these frameworks I'm finding that with Mach-II in particular several features have been added in 1.5 that, while named a little differently, provide functionality and/or syntax that is analogous of the features or syntax of either traditional Fusebox or Model-Glue. The "modules" feature added in 1.5 is a pretty decent analog to the "circuit" concept of Fusebox, which Mach-II didn't have before. And there's more planned for the future. In their Wiki right now, they have this to say about adding "broadcasts" in the upcoming Mach-II 1.6.

There has been discussions in the past that Mach-II does not allow for multiple listener notifications via a single "broadcast" command. Model-Glue's entire listener (aka controllers in Model-Glue) works on a broadcast system versus Mach-II somewhat more direct approach with the command. Any listeners that have a registered interest in a particular broadcasted message will receive the message for use. This allows you to invoke multiple listener methods by broadcasting a single message.

<snip>

..., message broadcasting lets you easily swap listeners by changing the messages it subscribes to and saves you from editing event handlers (and possibly introducing new errors). As a few people have pointed out in past discussions, these two reasons are a bigger maintenance issue than most developer realize.

That last sentence is somewhat telling also, because if you've read much of anything about cognitive science then you've probably come across an article or two about the overconfidence effect. But this talk of adding broadcasts in Mach-II just underscores this comment from the Fusebox FAQ.

Are Fusebox and Mach-II or Model-Glue competing frameworks?

Not really. They represent two different approaches to building an application. Both Mach-II and Model-Glue require an object-oriented approach to development. Fusebox does not require an object-oriented approach, but can support an OO approach if necessary.

ColdBox also requires an OO approach, although it is again a somewhat different approach than is prescribed by either of these other two. And there's my problem, the reason why it's taking me so long. The principles or fundamentals are mostly very similar, and the implementation details (code) may even be nearly identical, but the language changes between them. Each framework has to some extent invented a whole new lingo unto itself, describing the same thing (and my own is no exception).

So right now my article includes translations and code samples for the following concepts or tasks:

  • Organizational Sub-applications: Circuit / Module / Controller (some analogies are better than others)
  • Event (slightly different in each, but this has more linguistic similarity)
  • Browser Redirection
  • Nested / Chained Events (yeah, go figure)
  • Application Events (onApplicationStart, onSessionEnd, etc)
  • Pre / Post Events (ColdBox / Fusebox / onTap)
  • Business Logic (just how it's connected in the controller)

What you might notice in this list is that there's no mention of the view... yet. I got through to that point last night and left it there. The next thing for me to tackle is comparisons of the view. I have to show for example how XFA / XE / XEH is named and/or handled in each framework.

It's really not that writing this article is difficult, it's just tedious because it's a lot of research to see how each set of framework developers named the same things a little differently. I guess it's no wonder that nobody else has (as far as I know) taken the time to do this yet. Guys who get into frameworks I imagine fall into one of two categories - either they've studied the fundamentals forever and they expect others to follow the same series of trials and errors they went through, or they just found something they like and got comfortable and they don't really spend much time thinking about the alternatives. And in either case they usually don't feel like they have the time to create something like this, even if they did have the inclination.

Now I don't think either group of guys are bad folks -- I myself have been in the latter category for quite some time in spite of the fact that my "comfort framework" is one I designed myself. And Sean Corfield I think is in the former category. I actually feel pretty lucky to consider Sean a good friend even outside of our work or the industry, and I'm pretty sure it just never really occurred to Sean to write something quite like this not because he doesn't know how (because I'm sure he already knew most of the things I've learned in the last few weeks), but rather because he simply expects other people to do their own research and for the most part fall into the second category.

Anyway, I'll wheedle Sean more later. :)

For now enjoy and I'll probably release an initial draft of this perpetual WIP (Work In Progress) over the weekend.

Galleon Is Almost Here

So I'm finished with the first draft of Galleon ports for all 6 frameworks (2 different versions for Fusebox 5 to accomodate the non-xml mode). I've started working on the comparison articles. Not sure how long the articles are going to take me to write. I don't expect them to take as long as it took to actually port the application, but you never know. In the long run I think much of the comparison articles will really read like a generic frameworks "cheat sheet".

But ultimately it should show how choice of a specific framework is mostly not very important, simply because there's really not much difference between them when you get right down to it. It should help folks who're stalling, sitting on the fence, being indecisive trying to decide which framework they want to learn, but it will also mean that people won't really have the excuse anymore of "I don't have time to learn them" because all you'll have to do is read through my articles and viola! You'll understand at least 5 of them and probably by that point also have a pretty good generalized understanding of the concept of frameworks, not just the specifics.

Galleon Forums Status

So last week after I made the announcement, Luis Majano, the creator of ColdBox had replied to say that he'd like to give the ColdBox port another once-over, since he'd implemented most of that port a while ago on an older version of both ColdBox and Galleon. Though he also said he wouldn't be able to get to it until this week, which was fine by me because I had plenty to keep me busy. And I was right. I'm still working on the ports, although I'm making progress.

The onTap port was pretty quick and painless. One of the advantages there is that I didn't have to change any of the URLs, which wasn't true of any of the other frameworks. Galleon was written originally with a handful of base templates (pages) in the root directory and a separate handful in the /admin/ directory. So all the links are just relative links to different pages, much like you would see in a static HTML site (which is also how I'm writing my comparison article). And on the onTap framework this works fine, so in forums.cfm you'll find links like:

<a href="threads.cfm?forumid=#query.forumid#">
#htmleditformat(query.forumName)#
</a>

All I did was copy the original templates into the onTap directory, then copy them again to the /_components directory where I moved those around some, separated display into some includes and then edited the contents of the originals to use the framework by replacing the original code with <cfinclude template="#request.tapi.process()#">.

With the other frameworks collectively it was a bit more challenging. I had to perform a regular expression replacement of "(\w+)\.cfm to index.cfm?event=forum.$1& because all the other frameworks insist on everything being routed through index.cfm, creating the need for the event variable. But because URLs aren't always that simple, I couldn't stop there. I then had to replace instances of &? with ? and &" with " to account for the fact that not all the original URLs had query parameters. Then I had to replace all the instances of the regular expression ...rooturl#(\w+)\.cfm? with ...rooturl#index.cfm?event=forum.$1& for all the places where the URL had been embedded in an outgoing email. And there's still some question as to whether or not I've managed to get all the URLs properly rewritten.

It's one of the joys of porting to my own framework that I didn't have to mess with any of that. Although honestly I've never liked the fact that other frameworks insist on index.cfm in the first place. Call me old fashioned, I think the framework should take advantage of the fact that you can have more than one file in that directory. I suppose if I were using Fusebox I would probably rewrite the core files to use the file name as the name of the controller / circuit to use, so for example if I dropped onto index.cfm there would be a default fuseaction within the "index" circuit / event-handler and if I then went to "forums.cfm" there would be a different default fuseaction for the "forum" circuit / event-handler... but that's not the way Fusebox is written... Which I'll talk about a little more in my comparison article.

I also haven't copied the style sheets or any of the images to any of the frameworks (except the onTap framework) because none of the other frameworks make any commentary about where to place those files, so I just edited all the image sources and link tags to use the original sets. The onTap framework provides a little bit of automation for images and style sheets, so I have copied them there.

I also set up all the ports to reference the same ini file (/cfcs/settings.ini.cfm) from the original Galleon2 installation directory, so that if you decide to make any changes to the galleon settings, you'll only have to change them once. I should probably go back and delete all the other ini files that have been copied to the other ports to avoid confusion.

While not all of the frameworks have specific architectures for layouts (onTap and ColdBox both do), they all have popular techniques for creating layouts within their developer communities. So I've used those conventions for the other frameworks and have removed the custom tag Ray used originally for that purpose.

As it sits right now, I have 4 of 6 of the ports in a release-ready or nearly release-ready state and have just barely begun writing the comparison article. I've finished the initial draft of the ports for onTap, Model-Glue, Fusebox 5 (traditional) and am waiting on Luis to get back to me with his comments on the ColdBox port. I still have the Mach-II port to draft and another Fusebox 5 port to show Fusebox in non-xml mode. I will probably also do a little more work on the existing code for Model-Glue and Fusebox 5 because right now all the business objects are being referenced from within the view templates and I want to at least separate the bulk of that code away from the views into the controllers.

Porting Galleon Forums

So I decided to go ahead and work up the frameworks comparison by porting a small application to several different frameworks. I'll be using the latest versions of any frameworks I'm porting.

Here's my list:

I've contemplated also using ColdSpring or Lightwire to manage the business components with a single service layer across all the frameworks. I decided against doing this not only because I'm not a big fan in the first place but also because I decided not to write my own application to port to each framework. Instead I decided to port another open source application from another author and settled quickly on Ray Camden's Galleon forums. Why? Several reasons - it's popular, it's reasonably small, it's a "real world" application (as opposed to cfpetmarket.com) and there was already a port of it for ColdBox. Galleon already had its business objects implemented, so while some folks might like to see me add Lightwire or ColdSpring it's extra work for me that would be outside the scope of what I wanted to accomplish.

So I downloaded a copy of Galleon and a separate copy of each framework and where needed, the "app skeleton" for a couple frameworks. I installed the Galleon 2.2 database tables (I'm using SQL Server 2005 Express), configured my ColdFusion DSN in the administrator and installed the existing port of Galleon for ColdBox.

Here's where I hit my first snag. I'd just installed the Galleon 2.2 database, which I planned to use across all the frameworks. Well unfortunately the ColdBox port was done with Galleon 1.7 and the database wasn't entirely compatible. So I copied the updated CFCs from Galleon 2.2 into the ColdBox port and spent the next several hours weeding out a number of updates that needed to be made in the views (event handlers were mostly okay). I'm sure there are still problems with the ColdBox port, but I got it to a point where you can log in with it, etc. and I wasn't going for perfection, I just want to show generally speaking how these different frameworks handle the logic, application flow and separation of concerns. So even if the ColdBox example (or any of them) is still "buggy" when I'm done, it should be enough for people to see the fundamental differences (or mostly similarities) between these frameworks.

Once I got the ColdBox sample properly installed I then started copying the original Galleon 2.2 code into a clean copy of the latest version of the onTap framework. Several hours later I think I'm mostly done with it. One thing I did notice however is that the Galleon business objects use a string variable to identify which database platform is being used. The Galleon project came with install scripts for MySQL, SQL Server, Oracle and included an Access database file, all of which are supported natively by the onTap framework's SQL abstraction library. In the galleon business objects code, it uses that string to determine how to handle things like reserved words, so for example in the user.cfc you find this query:

<cfquery name="checkgroup" datasource="#variables.dsn#">
   select   id
   from   #variables.tableprefix#groups
   where
   <cfswitch expression="#lCase(variables.dbtype)#">
      <cfcase value="mysql">
         #variables.tableprefix#groups.`group`
      </cfcase>
      <cfcase value="oracle">
         #variables.tableprefix#groups."GROUP"
      </cfcase>
      <cfdefaultcase>
         #variables.tableprefix#groups.[group]
      </cfdefaultcase>
   </cfswitch> = <cfqueryparam value="#arguments.group#" cfsqltype="CF_SQL_VARCHAR" maxlength="255">
</cfquery>

I'm giving serious consideration to porting the business objects separately to use the framework's SQL Abstraction layer, even though I won't be doing this with any of the other frameworks because none of them have any equivalent features. The reason being that I think this is one of the nicer features of the onTap framework and really shows how it saves time and headaches during development, since the above query can be reduced to:

<cfscript>
var ds = getDatasource();
var thetable = variables.tableprefix & "groups";
var checkgroup = ds.getStatement("select").init(thetable,"id").filter("group",arguments.group).execute();
</cfscript>

Notice how that gets rid of that big nasty switch statement? Well that also means something else - it means that you could in theory run the application on another database platform (PostgreSQL for example) without modifying the business objects, simply by creating a new SQL Agent (CFC) for your preferred database platform. This is why I disagree with Ben Forta who says this kind of emulation is "not doable and not worth doing" (paraphrased).

Anyway, whether I port the business objects or not, once I'm done with the other three ports, I plan to write up a comparative analysis showing some of the strengths and weaknesses of the various architectures (as I see them, so yes, quite biased). I welcome both critique and criticism. :) The writeup will be included along with all the code in a zip archive that I'll upload here, including the core versions of all the frameworks I used (to ensure they're installed using a compatible version). To make sure the various versions use the same core framework versions I installed them on, I'll also be using the new application-specific mappings feature (this.mappings) in Application.cfc for each port. This means my distribution will require ColdFusion 8. I'll also include a summary of the writeup in my blog here and I'll cross-post to the riaforge forum for the Galleon project and each of the individual framework projects and probably the CF-Talk list.

And if there's anything you'd like to see me mention specifically in the writeup, just let me know either in the comments here or you can email me.

UPDATE: The first draft is available here.

Wikipedia

A while back I had gone and added a whole bunch of information about Coldfusion on Wikipedia. I remember being surprised how little information there had been about it at the time. All sorts of new information has been added to the article since then, but at the time it seemed sparse. I know I created the first entry for Allaire Corp.

Anyway this was a while after I'd started working on the framework and so of course at the same time I was creating an article for the onTap framework as well, knowing that there were already articles for Fusebox , Model-Glue and some other frameworks in other languages.

So today I went back to Wikipedia just to check on the article and see if maybe any of the content was out of date, because I know I frequently find information about myself in various places that claims I'm still in Austin or occasionally that I'm still in Ft Lauderdale. (I'm currently in Portland, OR.) And I figured chances were pretty good that there might be something in the Wikipedia article that wouldn't be accurate anymore.

So I log in to Wikipedia and it says I have messages. I have messages on Wikipedia?! I hardly ever edit anything there... It turns out someone had come across my entry for the framework and marked it as a stub. Okay fine, there was only one paragraph there so it wasn't exactly an in-depth article. If you look now, you'll see it covers the philosophy and history in depth, even including why the license changed from LGPL to BSD and what's up with the website. But that's not what my message was about.

Apparently while perusing the article about the framework and marking it as a stub, the BetacommandBot noticed that I'm apparently a Wikipedia NOOB and didn't specify a license for the Power onTap graphic. They were going to delete the logo on the Jan 22 (this coming Tuesday). Oops. Ya know, the graphic is part of the framework, you can even include it in your apps by using <tap:power /> in your xhtml templates. So it's covered by the OpenBSD license just the same as everything else. But in the previous description, I'd only mentioned attribution of the artist who created it for me, Russ Sharek an old friend of mine (though I did pay him $200 for it). So I changed the description to indicate the license in addition to the artist credit (because frankly, they deserve it), I'm just not sure still if I gave them the information in the format they want. Oh well. I guess I'll find out eventually.

I also added the framework to the Comparison of web application frameworks article. It's interesting to see how the majority of those frameworks have a bunch of empty cells in that table where either the author says "framework doesn't do this" or they didn't answer one way or the other, or they qualify the answer with "via thus and such extension". Personally I feel weird about the "via thus and such extension" answers for things like CFUnit and CFCUnit, but if Fusebox is going to claim those, then so am I! But it's nice to know that of all those things, aside from unit-testing and database migration, the onTap framework handles all of them natively in a CoC and DRY fashion.

Oh and I'd also like to reiterate that case sensitivity is a boil on the ass of software. Sing along with me! "Which one of these things is not like the other..."

They look pretty freakishly identical to me! And actually if you search for it in all lower-case letters in the search forms on the Wikipedia site, it brings you immediately to the correct article. The only time it brings you to this page that asks you to search for an "alternative spelling" (uhhh... that's right, capital letters is a totally different spelling), is when it's typed into the browser's address bar or when you come to it via a link like the one above where the spelling is different in the link URL.

So that in itself can cause external links to pages on Wikipedia from other sites to fail, simply because someone decided to change the capitalization of the URL! But it's also a headache when you're editing Wikipedia articles and trying to link to other articles within the Wiki and you have to check your edits for the red links instead of the blue links (indicating a mistyped article name). So if you wanted to be sure people actually arrived at that article, you would have to create a separate article with a redirect for each possible permutation of capitalization for the phrase!

And what happens if there's a red link indicating the article doesn't exist? It asks the visitor to create a new article! Because your link said "data" and the article title says "Data". And then the new article would be redundant and there'd have to be discussion of either deleting it or merging it with the original article!

View Surge!

500 views on the Members onTap plugin in the last 5 hrs? Really? ... hmmm... a quick scan of google shows the riaforge addresses at the top of the results for "Members onTap" immediately followed by some links to horribly outdated content from as far back as 2004, long before the SQL Abstraction layer was rewritten into CFCs. There don't appear to be any blogs yet linking to the framework projects on riaforge or to this blog... makes the traffic seem strange unless... perhaps Google is spidering the riaforge site. hmmm... Not that I wouldn't love to have that kind of legitimate traffic! :) But I don't think it's very likely that I'd suddenly get 100 views per hour sandwiched between Christmas and New Year's Day when the riaforge projects have only been up for a little over a week.

Edit Dec-28 9:00am: Yep... Number of views for the core framework shot up from slightly over 1k to slightly under 4k between when I posted this yesterday evening and now... That's roughly 3,000 views in 12 hours, roughly 250 views per hour or 4 per minute... As much as I'd like to take credit for that traffic, I really think it's spiders.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.5.006.