Union in QoQ Made an Enhancement Simpler

I was working with an app that would take an LDAP query from <cfldap> and do a bunch of processing against it. As it turns out, the LDAP query was targeted on an OU that wasn't grabbing all of the accounts it needed to process. There was a sibling OU that also needed to be included in the results.

I already had scope="SUBTREE" in the <cfldap> call, so I could've just set the context of the LDAP query to the parent of both OU's, but then it would grab a whole bunch of accounts that were in OU's that shouldn't be included in the processing. I could have restricted what was being pulled with a filter, but I already had several filters in the LDAP call and I didn't want to complicate that any further.

Well, think simpler then. What about just wrapping the LDAP call and its processing with a <cfloop>, executing against the different OU's each time? If the processing were simpler, that could've worked, but there is report generation and other stuff going on, and really all the accounts needed to be processed in one sweep.

There is still a simple solution: Query of Queries. Perform each LDAP call separately, then join the results together with a simple UNION statement.

<cfquery name="AllAccounts" dbtype="query">
   SELECT * FROM MyFirstLdapQuery
   union
   SELECT * FROM MySecondLdapQuery
</cfquery>

Now all the processing that occurs in my <cfoutput> tags that process the LDAP results will all happen in one sweep, with very few lines of code being altered, and none of my processing code had to be altered.

I simplified the code for this post, but in the app, the OU's are defined by a config file. So, the <cfldap> calls are executed in a loop, and then the SQL with the union statement is also generated by a loop based on the setting in the config file. So, at a later time, more OU's could be added with no additional coding required.

XML 101

The following are notes from the XML 101 class at Adobe MAX 2007. I'm skipping over the extremely basic XML principles and covering the more interesting stuff.

When use XML nodes over attributes? Attributes are good for set, simple values. If you have complex values, multiples of a particular entry, or you want more extensibility, use nodes for XML.

The presenter demonstrated using DTDs over XML Schemas. The DTDs use a very specific grammar that is not even XML-ish. It's kind of yesterday's XML descriptor. Nowadays, better to use XML Schemas, which are actually XML defining XML. Both are ugly in my opinion, and XML Schemas are more verbose (as XML usually is), but you might as well go with the latest, most accepted convention, which is the XML Schema approach.

By using DTDs and XML Schemas, apps can be cognizant of the structure of your XML language. Even from a developer's viewpoint, this can be useful when editing XML within an IDE.

The real fun part is formatting the XML with XSL (eXtensible Stylesheet Language). Supports loops, conditional logic, and other processing. Think of it as CSS on steroids, for XML. With XSL, you can transform XML to HTML, or PDF, or other fun stuff.

XPath is the heart of XSL processing. Allows you to traverse the XML document and find exactly what you're looking for, whether it's a particular node or looping over a group of items (xsl:for-each).

You CAN send the XML and XSL to the client and have the transformation be done client-side. All modern browsers include the XML/XSL engine. But generally it is wiser to do the transformation on the server side.

In my opinion, this approach lowers the value of XSL, because I can just as easily write some CF that will act on the XML. Yeah, I can write numerous XSLs for different presentations (text-only, XHTML, PDF, etc), but I'd have to do the effort of writing different XSL docs for that, when I could just as easily write different CF processors that accomplish the same thing. Unless you are working with a huge number of documents of varying types, XSL may not provide a large enough of an advantage for a language like CF that so easily manipulates XML.

The final step is grabbing XML with Ajax (such as Spry) that will populate document spaces (tables, divs, etc) with the XML data very easily as well. Again, this approach is similar to the CF approach, but with a more JavaScript-heavy slant.

Leveraging ColdFusion With AIR

AIR does not have a CFML engine. ColdFusion cannot be packaged within AIR apps. Traditionally, we use CF to generate the UI. However, in AIR, typically the UI is pre-designed and packaged. How does ColdFusion fit in, then?

Use ColdFusion apps directly, use ColdFusion as the data provider, or use ColdFusion as the data provider and as a UI provider.

To use a CF web app directly, just wrap it in a frameset. This is so kludgy, I can hardly stand it. But it will work to put your web app in a desktop app at some basic level. I suppose it could be handy since it hides the URL, it can make a more kiosk-ish look. Could also be useful if part of your app is a normal app, but part of it should mimic the web app exactly and you don't want to rewrite anything.

Better to use CF as a data provider.  ColdFusion is best at connecting with other systems, connecting to remote DBs, etc. Then communicate with web services, XML, flash remoting, JSON.  There is nothing new here, at this point, you just build typical connectivity that AJAX or Flash would use.

Flash remoting would probably be the best when using Flex. Provides a handy proxy-like access to your CFC.  Web services can also be done very easily with Flex.

Now, how about HTML/JavaScript (AJAX) in AIR? CFAjaxProxy, XMLHttpRequest, or plain HTTP (CF returns the data in XML, JSON, or text).

CFAjaxProxy. Makes a CFC available inside AIR app. Creates a JS proxy for a CF component. So on the CF side, you use cfajaxproxy, point it to a CFC, and instantiate the CFC in JS. Now, some initialization code is required. It is generated by the cfajaxproxy tag. So just copy the literal HTML/JavaScript generated by cfajaxproxy, and drop that into your HTML for AIR (just change the URL to the CFC to be the absolute URL; cfajaxproxy will write it as a relative URL).

It wouldn't hurt to just write some basic AJAX code on the web, using cfajaxproxy, and then copy that to your AIR HTML.

Now what about taking your apps offline? Well, you'll need to identify what is going to work offline, and store offline data (either to the filesystem or to a local database). Decide how the app will go offline: Modal (distinct offline/online mode, user driven, easiest to implement), or modeless (seamless offline/online mode, most of data is stored locally, better user experience but more work for the developer). Then, synchronization strategy: Manual sync, background client-driven sync, or server-driven sync.

Synchronization and online/offline management can be improved. They will describe more at the sneak peak session. Code samples will be at his website, http://coldfused.blogspot.com.

ColdFusion 8 Server Monitoring

The following are notes from an Adobe MAX 2007 session.

Server monitoring can help you get rid of some of your bottlenecks. Can make a big difference. The general server monitoring can even be used in production,  but DO NOT use the memory monitoring on a production site. May bring it down, even on low load.

The Overview Screen will let you see slow active requests, charts of the number of requests, average response time, etc. What errors have been thrown lately? What alerts have been posted (will explain later)? Various other statistics like that.

The Statistics Screen will display a bunch of various useful bits of info.

Requests. Active CF threads, slowest threads, active sessions, cumulative server usage, highest hit counts, cache status, etc. By looking at this info, you can find long-running active requests that can actually wreak havoc on the whole server. You start chopping those down, and before you know it, your server will run like a race horse. There's also a memory statistics section.

Memory. Shows general memory usage, requests by memory usage, threads by memory usage, queries by memory usage, sessions by memory usage, application scope mrmory usage. You may at times find large amounts of memory that aren't even used effectively in your apps, thus can slightly tweak the way things are being done. Beware: Garbage Collection isn't always the answer. Memory can be hidden in shared scopes or caches.

Database. Active queries, slowest queries, cached queries, etc. Most frequently run queries.

Errors. Requests with errors, requests that have timed out. Having a lot of errors used to cause stability issues; not as much now, although if your logs fill up the whole hard drive, ColdFusion will have a problem! Plus, if you're having that many errors, won't you want to know about it?

Alerts. Can set alerts for various circumstances you'll want to be notified on. If the hung thread count reaches a certain maximum, or if a thread has run for x seconds, you can do certain actions (send email, dump snapshot, kill thread, reject any more requests) or you can supply a processing CFC that can then do anything you want.

The Snapshots Screen will give you all the details of the server at the moment the snapshot was taken. Will save all the detail into a text file. Can't automate regular snapshots, although you probably could do it with the Admin API. Just set up a scheduled task that tells the Admin API to take a snapshot.

  Theme Brought to you by Directory Journal and Elegant Directory.