Adobe AIR LogoAdobe Integrated Runtime is more than just hot air, it traverses the previously unexplored space that exists between the Web and desktop applications.

Up until very recently, the void between the Web and the desktop seemed like a schism that could not be crossed. But since AIR’s 1.0 release in February this year, a whole host of other applications are emerging to compete with AIR in the single site browser space.

Although AIR is very new, the product is remarkably mature with the integration of the excellent opensource WebKit browser engine for rendering HTML and JavaScript, the SQLite database engine for embedded database functionality and of course, Adobe’s Flash player for development of Flash-based Rich Internet Applications. Because of this flexibility, the learning curve faced by developers is almost non-existent — they simply have to get to grips with the AIR API.

What is all the fuss about?

Delving into the AIR API, your application will have the ability to detect whether it is currently the active window or connected to the network. You can access the file system, allowing you to read and write files, access other datasources, tap into the native menu options or interact with almost any aspect of the operating system in a way familiar to common desktop applications. This functionality is available regardless of the architecture on which it is installed. Therefore AIR applications will work similarly when installed on a Windows PC or Mac, and soon on Linux machines as well.

AIR is much, much more than a single-site browser — it’s a cross-platform runtime environment and the distinction is significant.

The ability to run applications built on AIR on almost any machine, on- and offline, sets it apart from any other offering currently out there or in development. For example, Google Gears is restricted to AJAX applications, whilst Mozilla Prism isn’t much more advanced than a cut-down version of Firefox, with no offline capabilities yet.

Who else has entered the race?

As mentioned, a significant entry is Mozilla’s Prism, however, Pyro for Linux and Bubbles and Fluid for Mac are clever little tools for packaging up an existing website and presenting it as a standalone desktop application.

Mozilla Prism

Mozilla Prism LogoPrism, previously known as WebRunner is a product in development which integrates web applications with the desktop, allowing web applications to be launched from the desktop and configured independently of the default web browser. It is commonly used with Google AJAX Applications, such as Gmail and Google Docs.

Prism is part of an experiment by Mozilla designed to “bridge the divide in the user experience between web applications and desktop applications”. Essentially, Prism will allow you to create a desktop-like application out of individual websites. These site-specific applications are a growing trend and a trend heavily marketed by, not only Adobe, but now Mozilla, as ‘the future’.

While traditionally users have interacted mostly with desktop applications, more and more of them are using Web applications. But the latter often fit awkwardly into the document-centric interface of Web browsers.

In its current form, Prism doesn’t have the ability to function as a desktop application without access to the Internet, but Mozilla says it is “working to increase the capabilities of those apps by adding functionality to the Web itself, such as providing support for offline data storage and access to 3D graphics hardware.”

More details can be found on the Mozilla Prism website.

Pyro Desktop

Pyro LogoPyro Desktop is a new type of desktop environment for Linux built on Mozilla Firefox. Its goal is to enable true integration between the Web and modern desktop computing. Pyro was announced during GUADEC 2007 and is developed by Alex Graveley and Chris Toshok.

More details can be found on the Pyro Desktop website.

3D3R Bubbles

Bubbles LogoBubbles is a desktop application that allows you to work with your web resources in the way you want to work with them.

The Bubbles application window, known simply as a Bubble carries the web resource almost like a web browser does. Since the Bubble has advanced browser capabilities there’s an advanced control device for it — the Bubble seed — an XML file called Smart Bubble. It defines the properties — the whats & the hows — of its Bubble window. The Smart Bubble contains the information about what Bubble will load, how it will look on the desktop and what capabilities it will have, etc. So it goes from the Smart Bubble into a grown Bubble that lives on your desktop, accessible from the system tray.

More details can be found on the 3D3R Bubbles website.

Fluid App

Fluid LogoFluid is a way to create Site-Specific Browsers SSBs to run each of your favorite WebApps as a separate desktop application. Fluid gives any WebApp a home on your Mac OS X desktop complete with Dock icon, standard menu bar, logical separation from your other web browsing activity, and many other goodies.

Fluid includes optional Tabbed Browsing, built-in Userscripting (aka Greasemonkey/GreaseKit), RSS/Atom Feed detection, a JavaScript API for setting dock badges, showing Growl notifications and adding Dock Menu Items, optional bookmarks, optional browsing to urls outside the SSB “home” domain, Dock badges and Dock menus for Gmail, Google Reader, Facebook, Flickr, and Yahoo! Mail, auto-software updates via the Sparkle Update framework, and custom SSB icons.

More details can be found on the Fluid App website.

The ActionScript reference for rich Internet application development provides an alphabetical reference for all native ActionScript APIs for the Adobe technology platform runtimes: Adobe Flash Player and Adobe AIR—as well as the Adobe Flex framework APIs. Use this guide both as an API reference and a tool to learn about the ActionScript APIs available within the runtimes.

Download the ActionScript reference for RIA development (PDF 1.3MB)

The Adobe technology platform contains two primary runtimes. Flash Player is browser-based, and Adobe AIR is desktop-based. Because Adobe AIR is built on top of Flash Player, the Flash Player APIs are available within Adobe AIR. Consequently, Adobe AIR APIs are not available within Flash Player. The Flex framework is built on top of the Flash Player APIs, so it runs in both Flash Player and Adobe AIR. However, a number of Flex APIs take advantage of AIR APIs, and thus work only within Adobe AIR.

More information about this guide can be found on the Adobe Developer Centre Website.

Sweatshop is the leading specialist running retailer in the UK with 29 stores and 6 websites. We organise 2 of the largest road races in the UK and have been in business since 1971.

Sweatshop Logo

Over the next 18 months Sweatshop is looking to dramatically develop its websites, road races and retail operation. We are looking for key personnel to take the business forward as we intend to treble the size of the company in the next 5 years.

Objectives:
To improve the profitability and efficiency of the business by developing applications as required, and give the business much better access to the information it currently holds.

Role:
This role will involve re-authoring existing websites and helping to drive innovative new ideas and concepts throughout the business. This is a fantastic opportunity to drive the online side of the business forward.

Responsibilities:

  • Build web and IT automation to improve process and capability of the company.
  • Support and improve existing developments.
  • Build and implement new website functionality.
  • Build robust & scalable applications.
  • Build reports for existing systems.
  • Work with the senior management team to develop new business ideas.
  • Work with business users to specify and document requirements.
  • Estimate and report on effort required for all projects.
  • Communicate with business users and management, progress on all projects.
  • Manage own time effectively.

Qualifications:
A graduate calibre candidate with an appropriate technical qualification.

Essential Technical Skills:
Coldfusion technology, MS SQL server and MySQL, PHP, JavaScript, HTML, ASP, VB6/VB.net, Crystal reports.

Experience:
3+ years commercial development work including some time within an e-commerce environment or working for an established FMCG company.

Attributes:
Good communicator, Analytical, Ability to work on own initiative, Self starter.

Interested candidates:
If you’re interested and share the company values of ground breaking customer service, integrity, success, teamwork and the welfare of staff, write to:

Sarah Whatley, Sweatshop, 12 Station Road, Hampton, Middlesex TW12 2BX or
email HR@Sweatshop.co.uk

Salary:
£36k+ £40k+ (negotiable dependent on skills and experience)

Adobe AIR LogoSince the Adobe Integrated Runtime (AIR) was released at the end of February, we now have a stable platform on which to build desktop applications with our existing web skills. A number of people have already started and the Adobe AIR Marketplace is filling with AIR applications by the day.

So what is the big deal? The Adobe marketing team state that:

The Adobe AIR runtime lets developers use proven web technologies to build rich Internet applications that deploy to the desktop and run across operating systems. Adobe AIR offers an exciting new way to engage customers with innovative, branded desktop applications, without requiring changes to existing technology, people, or processes.

What AIR applications should you check out?

What is intriguing is that all the tools I have chosen are generally useful tools for the developer or designer, with the exception of twhirl, which is a social-interaction tool. I’m looking forward to when other, less developer-centric tools become freely available. AgileAgenda has taken the lead with this respect, albeit not freely available, as has eBay desktop, but I would like to see examples from the BBC in the form of a desktop BBC iPlayer or maybe a Flickr image browser, del.icio.us bookmark reader, RSS aggregator and a Picnik image editor.

Analytics Reporting Suite

Google Analytics Reporting SuiteThe Analytics Reporting Suite, by Nicolas Lierman, brings Google Analytics to the desktop. It uses it’s own custom API to interact with Google and nearly implements all the features of Analytics.

For website owners this is a must-have application. Like the twhirl AIR application below, it is a fantastic example of what can be achieved with Flex and AIR. Measuring visitor trends and traffic are essential tasks to managing and improving a websites performance. The Analytics Reporting Suite allows you to configure multiple Google’s Analytics accounts and access the web-based suite’s plethora of features via a desktop application. The application displays integrated graphs and animations via a tabbed interface, which allows you switch between a number of reports. These reports can then be saved as a PDF, Excel or XMLdocument, or printed.

You can download and install the application from the About Nico website.

twhirl twitter Client

Twhirl Logotwhirl, by Marco Kaiser, is probably the most popular desktop client for the twitter micro-blogging service. Most of the features available on the twitter website are accessible through twhirl, plus, a lot of usability enhancements have been added to make it easier to manage multiple accounts. This is great for those who want to separate business and personal accounts they may have.

The twhirl application is a great example of how AIR can bring web applications to the desktop; it can dock to the system tray, display message alerts and you can configure the applications opacity when not focused (great if you like Mac and Vista-styled themes). The application allows you to search twitter users, view their timelines, add friends, view followers, delete tweets and much much more. Twhirl automatically fetches your friends’ status updates, direct messages and replies, whilst also colour coding different types of messages and alerting you to messages both audibly and visually.

The twhirl application is skinnable and comes with several built in skins with which you can customise the application. All-in-all twhirl is not only one of the best twitter clients, but AIR applications.

You can download and install the application from the twhirl website.

Kuler Desktop

Adobe Kuler LogoAdobe kuler is the first web-hosted application from Adobe Labs designed both to stand alone and to complement Adobe Creative Suite software. Built using Adobe Flash and ActionScript 3.0, kuler is all about colour: colour for exploration, inspiration, experimentation and sharing. Kuler is clearly targeted at the designer, but anyone interested in colour will benefit from its use.

You can download and install the application from the Adobe Labs website.

WebKut

WebKut LogoWebKut is a web screenshot tool that allows you to capture web pages, or parts of them in a very simple way. It provides you with 3 capture options: the entire page, the current view, or only a selection. This little application proves particularly handy for those presentations or projects that need great visuals from the web.

You can download and install the application from the WebKut website.

RichFLV

RichFLV, by Benjamin Dobler, lets you edit FLV files. The key features include reading FLV metadata, read and edit cuepoints, cut FLV files, convert the sound from an FLV to MP3 format, convert an FLV to an SWF … and much more.

You can download and install the application from the Adobe AIR Marketplace website.

SearchCoders Dashboard

SearchCoders LogoThis Flex-based chat widget is designed with programmers in mind. The code input feature allows developers to chat about code without disrupting the conversation.

You can download and install the application from the SearchCoders website.

Pownce

Pownce LogoMuch like twhirl in look, feel and ease-of-use, but with a slant towards productivity rather than micro-blogging, Pownce is a way to keep in touch and share things with your friends or colleagues. You can send people files, links, events, and messages and then have real conversations with the recipients. This is a great collaboration tool and was one of the first services to really embrace AIR as an application architecture, which could realise their service as a desktop client. Everything that is available via the Pownce website is also available via the client application, except and possibly importantly, the ability for the user to amend their account settings and add friends to your network; this still has to be done via the website.

For a small annual amount, Pownce offers a paid-for service which will eliminate adverts from your profile and allow you to send huge file sizes (100MB) and customise the theme of your Pownce.

Pownce also offers Drupal integration and a mobile application, which works with the iPhone, BlackBerries and many more ‘internet-ready’ mobile devices.

You can download and install the application from the Pownce website.

With the release of ColdFusion MX 7 came the introduction of the Application.cfc ColdFusion component. This component replaced the traditional Application.cfm and OnRequestEnd.cfm ColdFusion application templates. Furthermore, if Application.cfc is present, both of these templates are ignored by the application.

In addition to replacing the Application.cfm, the Application.cfc introduced a number of built in methods that handle specific events. These events, as discussed in detail below, allow for a greater control over events within the application.

Application Variables

The THIS scope in the Application.cfc contains several built-in variables that allow you to set the properties of the application.

The following cfscript briefly outlines the variables that you can set to control the application’s behaviour.

<cfscript>
//the application name (should be unique)
THIS.name = "ApplicationName";
//how long the application variables persist
THIS.applicationTimeout = createTimeSpan(0,2,0,0);
//define whether client variables are enabled
THIS.clientManagement = false;
//where should we store them, if enabled?
THIS.clientStorage = "registry"; //cookie||registry||datasource
//define where cflogin information should persist
THIS.loginStorage = "session"; //cookie||session
//define whether session variables are enabled
THIS.sessionManagement = true;
//how long the session variables persist?
THIS.sessionTimeout = createTimeSpan(0,0,20,0);
//define whether to set cookies on the browser?
THIS.setClientCookies = true;
//should cookies be domain specific
//i.e. *.domain.com or www.domain.com
THIS.setDomainCookies = false;
//should we try to block cross-site scripting?
THIS.scriptProtect = false;
//should we secure our JSON calls?
THIS.secureJSON = false;
//use a prefix in front of JSON strings?
THIS.secureJSONPrefix = "";
//used to help ColdFusion work with missing files
//and directory indexes. tells ColdFusion not to call
//onMissingTemplate method.
THIS.welcomeFileList = "";
//define custom coldfusion mappings.
//Keys are mapping names, values are full paths
THIS.mappings = structNew();
//define a list of custom tag paths.
THIS.customTagPaths = "";
</cfscript>

Method Summary

Below is a brief discussion of the built-in event methods available to the Application.cfc. Since the Application.cfc is a regular ColdFusion component, you can also implement your own methods alongside the built in ones (assuming the names are uniquely different).

The onApplicationStart Method

Runs when the application first starts up: when the first request for a page is processed or the first CFC method is invoked by an event.

<cffunction name="onApplicationStart" returnType="boolean" output="false">
	<cfreturn true />
</cffunction>

This method is typically used to initialise code; for example to to set variables, such as datasource, into the APPLICATION scope, or create Singleton instances of ColdFusion components.

For example:

The following example creates structures in tha application scope to store general configuration settings and Singleton objects that can be later referenced by the application framework.

<cffunction name="onApplicationStart" returnType="boolean" output="false">
	<cfscript>
	// INITIALISE CONFIGURATION VARIABLES AND APPLICATION BUSINESS COMPONENTS
	// **********************************************************************
	// LOAD COMMON SITE VARIABLES INTO APPLICATION SCOPE
	// create structure to hold configuration settings
	APPLICATION.strConfig = structNew();
	//site-wide datasource(s)
	APPLICATION.strConfig.datasource = "DatasourceName";
	// default records per page for pagination
	APPLICATION.strConfig.recordsPerPage = 15;
	// **********************************************************************
	// LOAD PERSISTENT OBJECTS INTO APPLICATION SCOPE
	// data for object instantiation
	strArgs	= structNew(); // flush strArgs
	strArgs.datasource = APPLICATION.strConfig.datasource;
 
	// create structure to hold objects
	APPLICATION.strObjs = structNew();
	APPLICATION.strObjs.objUserManager = createObject("component","com.whatley.user.UserManager").init(argumentCollection=strArgs);
	//etc...
 
	// instantiate utility service objects
	APPLICATION.strObjs.objEmailServices = createObject("component","com.whatley.service.Email");
	APPLICATION.strObjs.objFileServices = createObject("component","com.whatley.service.File");
	APPLICATION.strObjs.objQueryServices = createObject("component","com.whatley.service.Query");
	//etc...
 
	// native coldfusion objects
	APPLICATION.strObjs.objServiceFactory = createObject("java","coldfusion.server.ServiceFactory");
 
	// **********************************************************************
	return true;
	</cfscript>
</cffunction>

Since the objects above are created as Singletons, we do not have to create or destroy objects throughout the application, but simply reference the object held in memory. This is efficient, but of course, would not be suitable for per-session objects, such as shopping carts.

For example:

Referencing and invoking an object from the APPLICATION scope:

<cfinvoke object="APPLICATION.strObjs.objUserManager" method="getUser" returnvariable="qryGetUser">
	<cfargument name="userId" value="#SESSION.strUser.userId#" />
</cfinvoke>

The onApplicationEnd Method

Runs when the application stops: when the application times out or the service is stopped.

<cffunction name="onApplicationEnd" returnType="void" output="false">
	<cfargument name="applicationScope" required="true" />
</cffunction>

This method is typically used to clean-up currently activities, save the current state of the application to a database or log the application’s end to a file. The latter can be useful to help determine when and why an application ended.

Below is a simple example of how you could implement a simple log:

<cffunction name="onApplicationEnd" returnType="void" output="false">
	<cfargument name="applicationScope" required="true" />
        <cflog file="#THIS.Name#" type="Information"
        	text="Application #ARGUMENTS.applicationScope.applicationName# Ended" />
</cffunction>

Notes:

  • The method is not associated with an individual request so you cannot use it to display data to a user.
  • If you call this method explicity, ColdFusion does not end the application, but does execute the code within the method.
  • The method can access the SERVER scope directly, but does not have access to the SESSION and REQUEST scopes.

The onMissingTemplate Method

Triggered when the user requests a ColdFusion template that doesn’t exist.

<cffunction name="onMissingTemplate" returnType="boolean" output="false">
	<cfargument name="targetpage" required="true" type="string" />
	<cfreturn true />
</cffunction>

ColdFusion invokes this method when it encounters a file not found condition, that is, when a URL specifies a CFML page that does not exist. This is an important addition to ColdFusion 8 and allows missing template errors (also known as HTTP 404 errors) to be captured more efficiently by the application framework.

The onRequestStart Method

Runs before the request is processed.

<cffunction name="onRequestStart" returnType="boolean" output="false">
	<cfargument name="thePage" type="string" required="true" />
	<cfreturn true />
</cffunction>

This method is great for user authorisation and login handling and for request specific variable initialisation. For example, you could use this method to log statistics to a database (performance and usage).

As this method runs at the beginning of a request, we can also use it to fire other events. In the example below, I reinitialise the Application which enables me to refresh objects held in memory that may have changed during code development or release.

<cffunction name="onRequestStart" returnType="void" output="false">
	<cfscript>
	//flush the application scope
	if ((CGI.server_name == "localhost") || (structKeyExists(URL,'refresh') && structKeyExists(URL,'password') && URL.password == "p455w0rd"))
	{
		onApplicationStart();
	}
	return true;
	</cfscript>
</cffunction>

The onRequest Method

Runs before the request is processed, but after onRequestStart.

<cffunction name="onRequest" returnType="void">
	<cfargument name="thePage" type="string" required="true" />
	<cfinclude template="#ARGUMENTS.thePage#" />
</cffunction>

This event handler provides an optional request filter mechanism for ColdFusion page requests. Use it to intercept requests to target pages and override the default behavior of running the requested pages. You can use this method to do preprocessing that is required for all requests. Typical uses include filtering and modifying request page contents (such as removing extraneous white space), or creating a switching mechanism that determines the exact page to display based on available parameters.

The onRequestEnd Method

Runs at the end of the request when all pages have been processed.

<!--- Runs at end of request --->
<cffunction name="onRequestEnd" returnType="void" output="false">
	<cfargument name="thePage" type="string" required="true" />
</cffunction>

This method can be useful for gathering performance metrics, or for displaying dynamic footer information (although I wouldn’t generally put display code in an Application.cfc).

For example:

Log the CGI variables to a database table.

<cffunction name="onRequestEnd" returnType="void" output="false">
	<cfset var qryInsertStats = queryNew('tempCol')>
	<cfquery name="qryInsertStats" datasource="#APPLICATION.strConfig.datasource#">
	INSERT INTO tbl_site_stats (template,query_string,referer,user_agent,remote_addr,datetime)
	VALUES
	(
		<cfqueryparam value="#CGI.PATH_INFO#" cfsqltype="cf_sql_varchar" />
		<cfqueryparam value="#CGI.QUERY_STRING#" cfsqltype="cf_sql_varchar" />
		<cfqueryparam value="#CGI.HTTP_REFERER#" cfsqltype="cf_sql_varchar" />
		<cfqueryparam value="#CGI.HTTP_USER_AGENT#" cfsqltype="cf_sql_varchar" />
		<cfqueryparam value="#CGI.REMOTE_ADDR#" cfsqltype="cf_sql_varchar" />
		<cfqueryparam value="#now()#" cfsqltype="cf_sql_datetime" />
	)
	</cfquery>
</cffunction>

The onError Method

Triggered when an error is encountered that is not caught by a try/catch block.

<!--- Runs on error --->
<cffunction name="onError" returnType="void" output="false">
	<cfargument name="exception" required="true" />
	<cfargument name="eventname" type="string" required="true" />
	<cfdump var="#ARGUMENTS#" />
        <cfabort />
</cffunction>

This method is used to handle errors in an application-specific manner. This method overrides any error handlers that you set in the ColdFusion Administrator or in cferror tags. It does not override try/catch blocks.

For example:

The following displays a friendly, static error page to the user if it is not a development server whilst also logging the error. If the error is on development, simply dump the error to screen for debugging.

<cffunction name="onError" returnType="void" output="true">
	<cfargument name="exception" required="true" />
	<cfargument name="eventName" type="string" required="true" />
	<cfif CGI.server_name neq "localhost" and CGI.server_name neq "127.0.0.1">
		<!--- Live application, handle error --->
		<cfinclude template="error/error.htm">
		<!--- Log all errors. --->
	        <cflog file="#THIS.Name#" type="error"
	            text="Event Name: #ARGUMENTS.Eventname#" >
	        <cflog file="#THIS.Name#" type="error"
	            text="Message: #ARGUMENTS.Exception.message#">
	        <cflog file="#THIS.Name#" type="error"
	            text="Root Cause Message: #ARGUMENTS.Exception.rootcause.message#">
	<cfelse>
		<!--- dump error for Staging and Development --->
		<cfif len(ARGUMENTS.eventName)>
			<cfdump var="#ARGUMENTS.eventName#" />
		</cfif>
		<cfdump var="#ARGUMENTS.exception#" />
	</cfif>
</cffunction>

The onSessionStart Method

Runs when your session starts.

<cffunction name="onSessionStart" returnType="void" output="false">
</cffunction>

This method is used for initialising SESSION-scoped data, such as a shopping basket and application form.

For example:

<cffunction name="onSessionStart" returnType="void" output="false">
	<cfscript>
	SESSION.start = now();
	SESSION.strShoppingBasket = structNew();
	SESSION.strShoppingBasket.items = 0;
	</cfscript>
</cffunction>

The onSessionEnd Method

Runs when session ends

<cffunction name="onSessionEnd" returnType="void" output="false">
	<cfargument name="sessionScope" type="struct" required="true" />
	<cfargument name="appScope" type="struct" required="false" />
</cffunction>

Use this method for any clean-up activities when the session ends. A session ends when the session is inactive for the session time-out period. You can, for example, save session-related data, such as shopping basket contents or whether the user has not completed an order, in a database, or do any other required processing based on the user’s status. You might also want to log the end of the session, or other session related information, to a file for diagnostic use.

Adobe Livedocs has a whole section dedicated to the Application.cfc.

I have created an example Application.cfc, which is available for download.

The THIS scope in the Application.cfc contains several built-in variables that allow you to set the properties of the application; the name, session management etc. With the release ColdFusion 8 comes the introduction of application-based pathing in the form of the THIS.mappings and THIS.customTagPaths variables.

The THIS.mappings variable can specify a structure that contains ColdFusion mappings. These settings take precedence over the mappings defined by ColdFusion Administrator Server Settings > Mappings page for the current application. Each structure element consists of the logical path as the key and the absolute path as the value. To use this variable, you must set the Enable Per Application Settings option on the ColdFusion Administrator Server Settings > Settings page.

For example:

<cfset THIS.mappings['/com'] = "C:\Inetpub\com" />

This is syntactically equivalent to using the structInsert() function:

<cfset structInsert(THIS.mappings, '/com', 'C:\Inetpub\com') />

The THIS.customTagPaths variable can specify a list that contains ColdFusion custom tag paths. These settings take precedence over the custom tag paths defined by the ColdFusion Administrator Server Settings > Mappings page for the current application. To use this variable, you must set the Enable Per Application Settings option on the ColdFusion Administrator Server Settings > Settings page.

For example:

<cfset THIS.customTagPaths = "C:\Inetpub\wwwroot\myAppOne\customTags" />

Since we can specify a list, this is also valid:

<cfset THIS.customTagPaths = "C:\Inetpub\wwwroot\myAppOne\customTags,C:\Inetpub\wwwroot\myAppTwo\customTags" />

Alternatively, we could represent the list as:

<cfset THIS.customTagPaths = "C:\Inetpub\wwwroot\myAppOne\customTags" />
<cfset THIS.customTagPaths = listAppend(THIS.customTagPaths, "C:\Inetpub\wwwroot\myAppTwo\customTags" />

For a long time, ColdFusion developers have needed the ability to define application-level settings actually in the application itself. These two new application-based pathing variables bring the ColdFusion developer a step closer to being able to produce out-of-the-box applications that can install in shared environments with little fuss and, more importantly, without the need to access the ColdFusion Adminsitrator to create the necessary mappings and custom tag paths.

Download the SQL Server 2005 JDBC Driver 1.2, a Type 4 JDBC driver that provides database connectivity through the standard JDBC application program interfaces (APIs) available in J2EE (Java2 Enterprise Edition).

This release of the JDBC Driver is JDBC 3.0 compliant and runs on the Java Development Kit (JDK) version 1.4 and higher. It has been tested against all major application servers including BEA WebLogic, IBM WebSphere, JBoss, and Sun.

BBC Homepage LogoI’m not a big fan of the BBC’s recent website redesign! While I believe that a few structural and hierarchical elements could have been addressed better, the overall result of this redesign is too “Facebook” and Web 2.0 for my liking; exactly what an online news site does not need. Who are the BBC trying to appeal to? They have gone from being content centric to design and technology centric. This in itself isn’t a bad thing, but I don’t understand the BBCs motivation for doing so.

Richard Titus, the Acting Head of User Experience at the BBC was a key driver of the project.

From a conceptual point of view, the widgetisation adopted by Facebook, iGoogle and netvibes weighed strongly on our initial thinking.

Titus identifies the key features of the new homepage as being:

  • Simple, clean and beautiful, the final design, … visually striking yet unpretentious.
  • Personalization: you can choose the content that interests you by adding and removing the content boxes via the “Customise Your Homepage” tab.
  • Localization: Users can now set their own location, enabling them to access local sites, weather, news, radio and TV schedules without the hassle often associated with user journeys to local content.
  • Simplicity: the customization is intuitive and includes an interactive demo and tips to guide users through the process. It is also unobtrusive – if the user has no desire to customize their page their experience won’t be compromised.
  • Search: The site is much easier to read and scan at a glance. At the top of the page there’s a search function (now reduced from two search boxes to one), and at the bottom a full directory of all BBC sites and a link to the A-Z, allowing users to quickly find what they’re looking for.
  • Nostalgia: the new homepage also manages to incorporate eccentricity alongside innovation.

Aesthetically bold and bright.

Aesthetically, the new homepage looks nice. It’s big, bold and bright - a far cry from the old days when BBC sites had text almost too small to read and a fixed-width design optimised for tiny monitors. But at the same time it appears far too clunky! I’d prefer something that would look a little more elegant and understated. Something that doesn’t appeal to The Facebook Generation, who are less likely to read the BBC pages at lunchtime, than update their Facebook, Bebo or Twitter profile during that ‘valuable’ hour. This begs the question, does the BBC know who their core audience is?

Confusing interactions.

The homepage makes great use of AJAX, but at the same time, there are a number of confusing interactions going on. For instance, the ‘Edit’ button next to each area of customisable content seems like the wrong label text. I’m not editing the news, the weather or blogs - I’m selecting which news categories I want to see, where I am and which blogs I want to read. These types of button ought to be contextual rather than generic. Edit is simply too vague.

Also, what’s the idea behind those plus and minus buttons for news? Strange idea. Add or remove articles from the displayed list? Why would you want to remove them from view sequentially? If the idea was to allow the user to asynchronously update a short list of available headlines, then why not move back/forwards in blocks of five? Plus and minus are often used as metaphors for creation/deletion in software, so the usage doesn’t seem right.

Personalisation vs Simplicity … an uneasy relationship

BBC Customise Homepage

The ability to personalise a website is, in general, a good thing. Google has done it with their iGoogle, Yahoo! with My Yahoo and Microsoft with Windows Live. But I think the balance here is gone too far towards design and borrowing from succesful Web 2.0 sites. The BBC website has always been an impressive destination for (relatively) impartial news and current affairs throughout the world, not a Web Portal. Or is this the point? Does the BBC want to become a destination for all your information needs and compete with Google, Microsoft and Yahoo?

The BBC should consider that 14-25 year old users, what I term The Facebook Generation, will require far greater scope for adding their individuality than is currently available. The social networking generation are page-savvy. They want control of their interface to information, their screen is their window on the world and I don’t think that you have gone far enough in divesting control of the display of that information to the user.

But for those who aren’t part of The Facebook Generation, the people who care about getting to the content fast and with little fuss, is the ability to personalise the homepage worthwhile or even simple? I’m not so sure.

Who needs a clock?

BBC Homepage Clocks Finally, the clock and date. What an important waste of webpage ‘real estate’, even though in the BBC’s case I understand it was a throwback to the old clock that preceded individual TV programmes. If you’ve got a modern computer capable of displaying the clock with the Flash plugin, then you’ll almost certainly have the date and time visible to you anyway. It’s needlessly superfluous on a website.

Following a conversation with a friend regarding how ColdFusion handles arrays and structures in ‘the background’, I was interested to find out what Java classes each were mapped to. This was a relatively simple case of using the functions getClass(), getSuperClass() and getName() to parse out the name of the Java classes.

<!--- Arrays (repeat up the hierarchy) --->
<cfdump var="#arrayNew(1).getClass().getName()#">
<cfdump var="#arrayNew(1).getClass().getSuperClass().getName()#">
<!--- Structures (repeat up the hierarchy) --->
<cfdump var="#structNew().getClass().getName()#">
<cfdump var="#structNew().getClass().getSuperClass().getName()#">

What became immediately apparent was that both were handled differently. In the case of a ColdFusion array, the parent class was the java.util.Vector, which seemed obvious. The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.

ColdFusion structures, however, are handled entirely differently, with the parent class being a coldfusion.runtime class. In fact, as we can see below, the code to handle a ColdFusion structure is entirely written for ColdFusion until the root class of java.lang.Object. Clearly ColdFusion does some complex wizardry to handle the complex nature of structues (associative arrays).

The class hierarchy for an Adobe ColdFusion array:

java.lang.Object
	java.util.AbstractCollection
		java.util.AbstractList
			java.util.Vector
				coldfusion.runtime.Array

The class hierarchy for an Adobe ColdFusion structure:

java.lang.Object
	coldfusion.util.CaseInsensitiveMap
		coldfusion.util.FastHashtable
			coldfusion.runtime.Struct

Being an inquisitive person, I applied the same code to Railo and BlueDragon, with equally interesting results.

The Java class hierarchy behind a Railo array:

java.lang.Object
	railo.runtime.type.ArrayImpl

The Java class hierarchy behind a Railo structure:

java.lang.Object
	railo.runtime.type.StructImpl

The Java class hierarchy behind a BlueDragon array:

java.lang.Object
	com.naryx.tagfusion.cfm.engine.cfData
		com.naryx.tagfusion.cfm.engine.cfJavaObjectData
			com.naryx.tagfusion.cfm.engine.cfArrayData
				com.naryx.tagfusion.cfm.engine.cfArrayListData

The Java class hierarchy behind a BlueDragon structure:

java.lang.Object
	com.naryx.tagfusion.cfm.engine.cfData
		com.naryx.tagfusion.cfm.engine.cfJavaObjectData
			com.naryx.tagfusion.cfm.engine.cfStructData

Adendum: Ben Nadel has a good little post on ColdFusion Data Types from Different Sources and How ColdFusion Sees Them.

Arrays and Structures are considered to be complex data types in ColdFusion. In contrast, simple data types are ones that contain a single piece of data, such as an Integer, String, or Boolean value. A complex data type can contain multiple pieces of data, which, in the case of arrays, are usually related. All the data are referenced under a single variable name. You can think of a complex variable as a variable that contains a collection of other variables inside it. An array maps Integers to arbitrarily typed objects (Integers, Strings, Booleans and Objects) while a structure, or associative array, maps arbitrarily typed objects to arbitrarily typed objects.

Arrays and structures are also known as reference types. A reference is an object containing information which refers to data stored elsewhere, as opposed to containing the data itself. References are fundamental to constructing many data structures and in exchanging information between different parts of a program. References increase flexibility in where objects can be stored, how they are allocated, and how they are passed between areas of code. As long as we can access a reference to the data, we can access the data through it, and the data itself need not be moved. They also make sharing of data between different code areas easier; each keeps a reference to it.

Array and structure reference types are pointers to a memory space. Pointers are the most primitive and error-prone but also one of the most powerful and efficient types of references, storing only the address of an object in memory. Because arrays and structures are pointers to a space in memory, it allows for easy copying of that data. However, when copying an array or structure, there is a distinct difference between how the copy is performed. This difference relates to the concepts of shallow and deep copying.

When copying an array, a deep copy is performed by ColdFusion. This means that the data is copied and a reference to the new copy is created in memory. Therefore, following the example below, a change in the value held at position 1 of array b will not over-write the value held in position 1 of array a as they have different memory references:

<cfscript>
	a = arrayNew(1);
	a[1] = 100;
	b = a; //deep copy for Array
	b[1] = 500;
	writeOutput(a[1]); // the returned result is 100
</cfscript>

We can also use the little-known Java function equals() to demonstrate that the two arrays are not equal (the references are different).

<!--- 
the following returns false
a and b do not refer to the same object
 --->
<cfdump var="#a.equals(b)#">

This is not the case for a structure. When copying a structure, as in the example below, a shallow copy is performed by ColdFusion. This means that a change in b.name will also result in a change of a.name:

<cfscript>
	a = structNew();
	a.name = "Simon Whatley";
	b = a; //shallow copy for Struct
	b.name = "John Doe";
	writeOutput(a.name); // the returned result is John Doe
</cfscript>

Using the equals() method, we can show that the two structures refer to the same object:

<!--- 
the following returns true
a and b refer to the same object
 --->
<cfdump var="#a.equals(b)#">

However, by using the duplicate() function, a deep copy of a structure can be performed:

<cfscript>
	a = structNew();
	a.name = "Wu Mingshi";
	b = duplicate(a); //deep copy for Struct
	b.name = "Ivan Ivanovic";
	writeOutput(a.name); // the returned result is Wu Mingsh