back

Comparing Adobe Flex and Ajax development models

by Brian Rinaldi

As the web has matured, application developers have been working to move from the standard request/response model used by traditional web applications to a richer experience that better mimics the functionality of desktop applications. In essence, there are two separate, but not mutually exclusive, development models for creating rich Internet applications (RIAs): Ajax and Adobe Flex. In this article, I provide a brief history and description of both Ajax and Flex and compare the two technologies.

Ajax

According to Jesse James Garrett, the person who coined the term Ajax in 2005, "Ajax isn't a technology. It's really several technologies...coming together in powerful new ways."

The term Ajax comes from the acronym for Asynchronous JavaScript and XML (AJAX) but has morphed into far more than the acronym itself describes. As the acronym implies, the core of Ajax is making asynchronous calls to load XML data using JavaScript. In other words, Ajax uses the browser as its runtime, and the browser exchanges a small amount of data with the web server (behind the scenes) and therefore eliminates the need for entire page refreshes. This technique increases responsiveness and interactivity, and provides a richer, more desktop-like application experience for end users. Ajax has been around for a while but was recently popularized by several innovative companies, including Google, which is heavily invested in Ajax with Gmail and Google Maps.

Standard XMLHttpRequest

Now let's take a look at the XMLHttpRequest component, which is at the core of Ajax development. The XMLHttpRequest component enables browsers to make dynamic and asynchronous data requests without having to reload a page.

By default, Ajax requires no framework. It utilizes JavaScript functionality that has been available in most modern browsers for years. However, it is implemented differently across the major browsers — so as with any complex JavaScript, cross-browser compatibility issues arise when you use XMLHttpRequest. For example, in Microsoft Internet Explorer the XMLHttpRequest is an ActiveX object, while in most other browsers, such as Mozilla Firefox, it is a standard JavaScript object. Once the object itself is created, however, functionality is essentially the same.

The primary attributes in an XMLHttpRequest are establishing the URL that will return the data (text or XML) and a callback function. The callback function is the JavaScript function that gets called whenever the XMLHttpRequest's processing state changes, such as when data is returned (among other available states). While asynchronous and synchronous modes are both available, it is generally considered best practice to use asynchronous mode. Synchronous mode will wait for the request to return and block the UI from responding before processing the remainder of the script, while asynchronous mode does not. The mode is established by a Boolean flag in the open() method of the XMLHttpRequest object, such as xmlhttp.open("GET",url,true);.

The following example (based on source provided by W3Schools) shows a simple XMLHttpRequest to retrieve an XML object containing the body of a blog post that is posted to an HTML div element on the page. The call is to a ColdFusion component; however this component is designed to simply serve up an XML document, and ColdFusion is primarily involved as the connection to a data source.

Here is the ColdFusion component function that returns the contents of a post in XML format:

<cfcomponent output="false">
<cffunction name="showPost" access="remote" output="true" returntype="void">
<cfargument name="id" type="UUID" required="true" />

<cfset var getPost = "" />
<cfset var post = xmlNew() />
<cfset post.xmlRoot = xmlElemNew(post,"posts") />
<cfset arrayAppend(post.posts.xmlChildren,xmlElemNew(post,"post")) />
<!--- this would actually go elsewhere, but for the sake of example... --->
<cfquery name="getPost" datasource="flexcampboston">
SELECT *
FROM entry
WHERE id = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.id#" />
</cfquery>
<cfset post.posts.post[1].XmlCData = getPost.content />
<cfcontent type="text/xml" reset="true" /><cfoutput>#toString(post)#</cfoutput>
</cffunction>
</cfcomponent>

This code simply creates a function that can be accessed via the URL that accepts a single argument, which is the ID of the post I wish to display. It then creates a ColdFusion XML object and places the content of the blog entry into the CDATA block of a post node in the XML object. CDATA is used in this case because the content of the entry includes HTML elements. The XML is then output as a string to a page with a content type (that is, a MIME type) of XML.

Now, let's look at the HTML that contains the asynchronous HTTP request:

<html>
<head>
<title>Simple XMLHTTPRequest Example</title>
<script type="text/javascript">
var xmlhttp;

function loadXMLDoc(url,callback) {
xmlhttp=null;
// code for Mozilla, etc.
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject) {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (xmlhttp!=null) {
xmlhttp.onreadystatechange=callback;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
else {
alert("Your browser does not support XMLHTTP.");
}
}
function checkReadyState(obj) {
if(obj.readyState == 4) {
if(obj.status == 200) {
return true;
}
else {
alert("Problem retrieving XML data");
}
}
}
function showPost() {
var post = null;
// if xmlhttp shows "loaded"
if(checkReadyState(xmlhttp)) {
post = xmlhttp.responseXML.documentElement.getElementsByTagName("post");
// alert(post[0].firstChild.data);
document.getElementById('content').innerHTML = post[0].firstChild.data;
}
}
</script>
</head>
<body>
<a href="#" onclick="loadXMLDoc('http://localhost/ajaxexamples/xmlhttp/ getPostRemote.cfc?method=showPost&id=F13CF2F6-A61A-8116-ACAAC9C3188619B1', showPost)">Agenda</a><br />
<a href="#" onclick="loadXMLDoc('http://localhost/ajaxexamples/xmlhttp/ getPostRemote.cfc?method=showPost&id=F180589F-DFC4-7D2B-F17B9DD2ADAC0CE7', showPost)">First Post</a>
<div id="content">Loading...</div>
</body>
</html>

In this example, you can see that the loadXMLDoc() implements a standard cross-browser approach to the XMLHttpRequest. It also enables you to specify the URL you want to retrieve and the function you want to use as the callback. The checkReadyState() function just validates the status for the request and, when it is complete, verifies that the request status comes back showing it succeeded. Lastly, the showPost() function assigns the value of the post XML node to the content div. This is all triggered by the onclick event of the links in the document. This example could easily have passed the HTML back as plain text (via xmlhttp.responseText) rather than XML, but I wanted to display an example that could be extrapolated to suit more complex data.

For more examples, see W3Schools.

Third-Party JavaScript libraries

Ext JS, Yahoo User Interface (YUI) Library, and jQuery are all examples of popular prebuilt libraries for handling Ajax development. While all these libraries generally include methods to handle the sending and loading of asynchronous data, the primary benefit of these frameworks (and others like them) is the included utilities and UI tools.

These libraries include prebuilt components for handling things like grids, trees, windows, tabs, and forms, among other utilities. (Note that in jQuery these elements are available in a separate UI library that was recently released.) The other benefit is that cross-browser issues are generally resolved within the framework itself. Each library works in a variety of browsers, including Internet Explorer, Firefox, Safari, and Opera — but with some notable version limitations.

Flex

In 2002, Macromedia (now Adobe) released Flash Remoting, which made it truly possible to use Adobe Flash Player as an application platform rather than an animation tool by enabling you to quickly connect Flash Player to a data-driven application model. Unfortunately, most application developers found that the programming model and IDE for Flash, which was dependent on things like a Stage and Timeline designed for animation, made development difficult and uncomfortable. To help bridge that gap, Macromedia released Flex in 2004, which uses a prebuilt library of components designed specifically for creating RIAs. Flex enables you to build applications on top of the Flash Player virtual machine using an XML-based coding language (MXML) within an IDE geared more toward developers than designers, called Flex Builder. Applications created with Flex are deployed via Flash Player. In 2007, Adobe announced it will release the Flex 3 SDK as open source under the Mozilla Public License. This enables the user community to extend or improve the Flex framework via contributions.

Flex has received a lot of attention within the development community, partially because of the reach of Flash Player with its ability to display rich user interfaces consistently across platforms and browsers, and partially because of the level of client interactivity the Flex framework provides. Many large corporations — including Google, Yahoo, eBay, and other trend-setting companies — have adopted Flex within their development environment. However, you should consider a few things when using Flex. First, Flex 2 requires that a client have Flash Player 9 installed because of its dependency on the ActionScript 3.0 language. As of January 2008, Flash Player 9 is installed on 93% of Internet-connected computers, but if your users do not have Flash Player 9, they will need to download it to view your content. In addition, the development community for Flex is smaller than the development community for Ajax, partially because Flex is new and partially because it has a steeper learning curve, requiring knowledge of both MXML and ActionScript. This can make it more difficult to find developers to work on your project.

Standard MXML with RemoteObject call

Once you are comfortable in MXML and ActionScript 3.0, Flex makes it easy to rapidly build rich application interfaces. You can easily tie these interfaces into existing services by making remote calls using the RemoteObject tag.

To see how simple this can be, let's replicate the W3Schools example from earlier using a Flex DataGrid and a remote call to a ColdFusion component using Flash Remoting. By default, ColdFusion includes Flash Remoting, and Flex has built-in ColdFusion connectors. It is important to note, however, that Flash Remoting is not required to use Flex since Flex can connect via web services or standard HTTP calls.

First, let's look at the ColdFusion component we are going to call. It is similar to the one provided for the Ajax example we looked at earlier; however, in this case, we don't need to do any of the formatting for an HTML data grid. Instead, we simply return the query. Even though Flex has no concept of a query data type, it automatically converts this to an ArrayCollection data type because of the Flex and ColdFusion integration:

<cfcomponent output="false">
<cffunction name="getAllPosts" access="remote" output="true" returntype="query">
<cfset var getPosts = "" />
<!--- this would actually go elsewhere, but for the sake of example... --->
<cfquery name="getPosts" datasource="flexcampboston">
SELECT name,title,last_modified
FROM entry
</cfquery>
<cfreturn getPosts />
</cffunction>
</cfcomponent>

Our MXML template consists of 25 lines of code. This code lays out the RemoteObject, which is our ColdFusion component and method as shown above, and a DataGrid as well as a couple of simple functions that call our remote method and assign it to the grid:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
<mx:RemoteObject id="postServices" destination="ColdFusion" source="flexExamples.com.getPostRemote" result="setPosts(event)" fault="Alert.show(String(event.fault)), 'Error'">
<mx:method name="getAllPosts" />
</mx:RemoteObject>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
public var posts:ArrayCollection = new ArrayCollection;

private function initApp():void {
postServices.getAllPosts();
}
private function setPosts(event:ResultEvent):void {
posts = event.result as ArrayCollection;
}
]]>
</mx:Script>
<mx:DataGrid id="showPosts" dataProvider="{posts}" width="500" height="400" />
</mx:Application>

In this code, you can see that when the application is finished loading, it calls the initApp() function, which initiates the remote call to the getAllPosts() function of my getPostRemote component. In this case, the RemoteObject defines a result callback method as setPosts(), which simply assigns the contents of the result to a predefined variable. The DataGrid itself has a binding within the dataProvider attribute that binds the contents of the grid to the posts variable, which we populated in the setPosts() method.

Using Flex with LiveCycle Data Services and BlazeDS

Adobe LiveCycle Data Services (LCDS) ES software adds several enterprise-level features to Flex application development. LCDS includes a long list of features; however the key items are generally the real-time client-server data synchronization that can push out data changes to any number of clients viewing the same data, as well as the conflict resolution that assists in dealing with conflicts within simultaneous changes to data.

BlazeDS is another open source application announced by Adobe recently with a great deal of fanfare. Essentially, BlazeDS incorporates a key subset of the LCDS functionality, including the ability to directly invoke Java objects. It also includes the messaging features of LCDS. A key differentiator, however, is that the data synchronization is not real time because BlazeDS uses HTTP polling and HTTP keep-alive instead of RTMP. Nonetheless for many applications, near real time meets the requirements just as well as actual real time, so having BlazeDS as a free option is an enormous plus.

Developing Adobe AIR applications

I can't go much further without mentioning Adobe AIR, which is a cross–operating system runtime that enables you to build Flex and Ajax applications that run as desktop applications. In other words, Adobe AIR lets you break free from the confines of the browser. This means you can do things like access the file system without worrying about browser compatibility. In addition, Adobe AIR applications run identically across currently supported operating systems.

This means that you no longer need to build web applications that behave like desktop applications. Instead you can expand your web applications to include the desktop. Since Adobe AIR enables both Flex and Ajax development, you can leverage both your existing codebase and your existing talent to develop desktop applications with Adobe AIR. In fact, Adobe AIR provides a level of interactivity between Flex and JavaScript that cannot currently exist within a browser. For example, ActionScript functions can natively call JavaScript functions and vice versa.

Although Adobe AIR is currently still in beta, it has been receiving widespread attention, and many companies such as eBay, Nickelodeon, and NASDAQ are already using the runtime in production applications to further enhance or support their online Flex or Ajax applications with offline functionality. The standout benefit is that you can utilize the current skillset of your application developers in HTML, JavaScript, and Flex to create desktop applications with rich interfaces.

When to use Flex vs. Ajax

While there are no hard and fast rules about when one technology is a better fit, it is important to keep in mind some key considerations such as download size and client browser support. However, it is also worth stressing that one technology is not necessarily better than the other. Often the requirements of a specific project determine the better solution.

For example, Flex might not be the right choice for a text-heavy, public-facing application because Flash Player is less efficient at handling large amounts of text than the browser. Alternatively, Ajax might not be the right choice for an application with complex interactivity requirements because, with no IDE, development and debugging can often be complicated.

The two technologies can also work together. In fact, Adobe has created a Flex-Ajax Bridge (which is included as part of Flex 3 and is available for earlier versions in Adobe Labs) that facilitates communication between JavaScript and a Flex SWF. Also since Flex applications compile into SWF, they can be added to any web page just like any regular Flash SWF. This means you are not required to make the entire page a Flex application. Instead you can create widgets or sections of a site with Flex while you create other sections of the site with Ajax.

For example, Google Finance mixes charts rendered in Flash Player with JavaScript-enabled links to create interactivity between the two. James Ward, technical evangelist for Flex at Adobe, has an Adobe Acrobat Connect presentation covering this topic.

The point is that you have options, which is always a good thing. The following are some important things to consider when choosing the right technology for a particular project:

References


Brian Rinaldi is as a Content and Community Manager for the Adobe Developer Center team, where he helps drive content strategy for HTML5 and JavaScript developer content. Brian blogs regularly at http://remotesynthesis.com and is a unreformed twitter addict @remotesynth.