Building RIAs on J2EE Foundations

Joe uses ColdFusion 8 to design and build an AdobeFlex RIA that enables collaborative management of a list of tasks using a rich front-end and real-time communications.


July 30, 2008
URL:http://www.drdobbs.com/web-development/building-rias-on-j2ee-foundations/209900484

Joe builds and develops Adobe ColdFusion, Flash, Flex, and Ajax applications for all manner of organizations. He can be contacted at www.firemoss.com.


I've been hooked on Rich Internet Applications (RIA) since the release of Adobe Flash 5. Unlike traditional HTML-based web applications, RIAs take advantage of client runtimes (like Adobe Flash Player) to deliver engaging user experiences. For instance, to write this article I used an Adobe RIA called "Buzzword" (labs.adobe.com/technologies/buzzword), a full-featured word processor running within my browser that lets me collaborate and work simultaneously—functionality that can't be found in traditional HTML-based web applications.

Adobe Flex RIAs become even more useful to users when they use server-side components for connectivity to databases, media, and other services. I've developed the server-side of RIAs using Java, SOAP, .NET, PHP, Rails, and ColdFusion. In the process, ColdFusion has become my application server of choice for RIA service layer development. Why? Because ColdFusion combines straightforward development with features such as Flash Remoting and real-time messaging gateways that simplify communication between the application server and Flex RIAs.

To see why ColdFusion is an important addition to a RIA developer's toolbox, in this article, I design and build a Flex application using ColdFusion 8. This application, named "Task List," enables collaborative management of a list of tasks using a rich front-end and real-time communications; see Figure 1. The complete source code for the Task List application is available online (www.ddj.com/code/).

Figure 1: The Task List application.

The goals of the Task List application include:

Building the Flex UI

To get started, you need to set up a development environment for writing your Flex and ColdFusion source code. For building Flex applications, you can use Adobe Flex Builder 3, which can be installed as a standalone application or used to add Flex development tools to an existing Eclipse environment. Flex Builder 3 provides code editing with full code-assist and documentation for both ActionScript 3.0 and MXML, the two languages used to create classes in Flex.

ActionScript 3.0 is an ECMA language designed for developers accustomed to Java, C#, JavaScript, or C. It uses semicolons at the end of lines and curly braces for blocks. In a Flex RIA, ActionScript 3.0 is used primarily to model application entities and behavior. MXML, on the other hand, provides a simple tag-based language for declaratively creating classes. It is a flavor of XML, and is primarily used to define user interfaces. To handle events and behavior, it can contain embedded ActionScript 3.0 code.

In addition to its code editor, Flex Builder 3 provides a full-featured visual editor for MXML interfaces. You can drag-and-drop controls from tool palettes into desired locations within the interface. Once you place the controls, you can use toolbars to modify control properties, apply Cascading Style Sheet (CSS) attributes to change their look-and-feel, and even bind controls to data or ActionScript 3.0 classes. Because the visual editor is extensible, you can add and manipulate your own developer-defined controls as if they were native Adobe controls.

To examine your application at runtime, Flex Builder 3 provides an interactive debugger built on top of the existing Eclipse debugger framework. This provides a view of breakpoints, variables, and expressions that's almost identical to ColdFusion or Java debuggers. If you need to examine memory or processor utilization, an interactive profiler is also available.

To begin building Task List, install ColdFusion 8, Flex Builder (which includes the Flex SDK), and the CFEclipse Eclipse plug-in for ColdFusion (www.cfeclipse.org). Use the Flex Builder 3 New Project wizard to choose a ColdFusion server deployed within a JBoss environment.

When the wizard completes (and if you were creating a Flex project using Java as a back end), you create and edit a number of Flex-specific XML files in the server-side Java application server's configuration directories. The instant the wizard completes, ColdFusion creates a Flex application that is already connected to a ColdFusion server. The Flex application's source code and debugging builds are stored in your Eclipse workspace.

With a client-side Flex project created, you can now create a client-side model of your single domain object. Right-click the Task List project in the Flex Builder 3 Flex Navigator pane and choose New ActionScript Class to get started. Using the wizard, create a Task class and place it within the com.firemoss.tasks package. When the wizard completes, the actual source-code file is in the project's src/com/firemoss/tasks directory. (When you download the code accompanying this article, you'll find the source code for this class in Tasks/src/com/firemoss/tasks.)

package com.firemoss.tasks.model
{
    import mx.utils.UIDUtil;
     // Alias'd to server-side class / component
      [RemoteClass(alias="com.firemoss.tasks.model.Task")]
    // Bindable makes this class a subject for data binding
      [Bindable]
    /** Model of a Task. */
    public class Task
    {
        /** Unique Id. */
        public var id:String = UIDUtil.createUID();
        /** Name of the task. */
        public var task:String;
        /** Is the task complete? */
        public var complete:Boolean;
    }
}

Listing One

Listing One provides ActionScript 3.0 Javadoc-like comment capabilities for automatically generating documentation. Annotations within square braces let metadata be added to the class. Using the ASDoc utility within the Flex SDK, you can produce API documentation for your ActionScript 3.0 classes. In the Task class, annotations are used to add two key metadata items:

With the model of a Task created, turn to the UI. When the Flex project wizard completes, it creates the Tasks.mxml file to act as the main interface. Because the application is simple, it employs the Autonomous View pattern for its sole UI, embedding within Task.mxml all knowledge of the model, services, and control code. (In larger Flex applications, you should use more scalable architectures, such as Model View Controller.)

Inside Tasks.mxml, MXML tags define properties and server connections. In Listing Two, Task instances are stored using classes from the Flex SDK's Collections API. An ArrayCollection stores a list of all tasks, and a ListCollectionView subscribes to the master collection and defines an automatically updated subset of tasks that are complete. Both of these collections are "bindable," which means they can serve as a subject for observation by other classes and UI controls. When the subject object changes its properties, observers are notified and may update themselves accordingly. This provides a loosely coupled architecture ideal for creating flexible, engaging UIs.

<!-- MODEL -->
<!-- Master list of all tasks -->
<mx:ArrayCollection id="tasks" />
<!-- Filtered list of completed tasks -->
<mx:ListCollectionView 
    id="incompleteTasks" 
    filterFunction="filterIncompleteTask" 
    list="{tasks}"/>

Listing Two

Once data is stored in collections, Task List needs to display a list of tasks. It does this in Listing Three with a List component that shows a vertically scrolling list of items. The List instance is bound to the currently selected collection of tasks. As the collection changes, List automatically redraws itself.

<!-- List of tasks -->
<mx:List
    id="taskList"
    height="100%" width="100%"
    labelField="task"
    dataProvider="{showCompletedTasks.selected ? tasks : incompleteTasks}"
    change="taskListChangeHandler(event)">
    <mx:itemRenderer>
        <mx:Component>
            <view:TaskItemRenderer />
        </mx:Component>
    </mx:itemRenderer>
</mx:List>
Listing Three

By default, List shows a label for each of its items. However, Task List needs to show both the label and a CheckBox to enable user interaction. Any of Flex's list-based controls can employ a custom item renderer, which is typically an MXML-based class that defines a UI for each item. In Task List, I use a custom renderer that displays a CheckBox and the task's name.

Below the list of tasks, the application must display a form to let users enter new tasks; see Figure 2. MXML includes a rich set of form controls. By combining tags like Form, FormItem, TextInput, and StringValidator, you create a form with complete client-side validation solely through declarative tags.

Figure 2: Flex Builder 3 provides a WYSIWYG editor for visually editing an application's UI.

Last on Task List's set of defined MXML elements are server connections. Flex provides a RemoteObject tag for RPC-style communication with server-side ColdFusion and Java components. In Task List, a RemoteObject tag using the preconfigured "ColdFusion" destination lets the application communicate with a server-side ColdFusion component.

For real-time messaging, Flex provides Producer and Consumer tags. A Consumer lets an application subscribe to real-time messages published by the server. A Producer publishes messages to the server for rebroadcast to other users of the application. In Listing Four, a Consumer tag using the preconfigured "ColdFusionGateway" connection lets ColdFusion send real-time messages to the Task List application running within the user's browser.

<!-- BUSINESS SERVICES -->
<!-- Subscribes to realtime messages from the application server -->
<mx:Consumer 
    id="consumer" 
    destination="ColdFusionGateway" 
    message="taskMessageHandler(event)" />
<!-- Allows RPC-style invocations of server-side service methods -->
<mx:RemoteObject 
    id="taskService" 
    destination="ColdFusion" 
    source="com.firemoss.tasks.service.TaskService" >
    <mx:method name="listTasks" result="listTasksResultHandler(event)" />
    <mx:method name="saveTask" />
</mx:RemoteObject>

Listing Four

To wire all of these MXML components together, Task List uses ActionScript 3.0 functions within Tasks.mxml that act as event handlers. These event handlers define what actions are taken when users indicate task completion or click the "OK" button to add a new task. They also handle real-time task updates received from the server; see Listing Five. With event handlers in place, the client-side Flex application is ready to be used.

/** Invoked when the server completes an operation of taskService */
private function listTasksResultHandler(event:ResultEvent):void
{
    // Server returns an Array of Task instances: update our model.
    this.tasks.source = event.result as Array;
}

Listing Five

Creating the ColdFusion Service Layer

A Flex RIA is the client-side component of the application. It only runs within the browser, requiring a server-side component for interaction with databases and message queues. For the Task List application, the service layer is provided by ColdFusion running within a local JBoss environment.

To create the ColdFusion infrastructure, I downloaded and installed the free developer edition of ColdFusion 8 from the Adobe website, selecting a JEE-style installation that results in a WAR file. After expanding the WAR into a directory structure, I copied it to my JBoss server's deployment directory, using a context-root of /tasks. Visiting http://localhost:8080/tasks/CFIDE/administrator completed my installation and displayed the ColdFusion management application.

While I could have used PHP, .NET, or other server-side technologies, I chose ColdFusion because it makes real-time messaging straightforward. When you're in the management application, you're ready to perform the single-step process of configuring the real-time messaging infrastructure. This consists of creating an "Event Gateway," providing a conduit from ColdFusion to an external system such as the Flex messaging infrastructure. Task List uses a gateway instance named taskGateway that lets ColdFusion code send real-time messages to the Flex application via the configured-by-convention ColdFusionGateway destination. The point-and-click UI in the ColdFusion administrator lets you create this real-time messaging bus without having to find and install dependency JARs, edit XML files, or deal with other complicated configuration chores.

Just as with the front end, designing the back end begins with the construction of a Task model. Next, you design an interface and implementation of a Data Access Object for persisting and recalling Tasks. Finally, you develop a simple Façade pattern implementation exposing coarse-grained functions such as listTasks() and saveTask() to your Flex application.

CFEclipse provides an ideal development environment for writing ColdFusion-powered Flex applications. Because it is an Eclipse plug-in, CFEclipse acts as an add-on to Flex Builder 3, letting you work in a single IDE as you work with both the server and client sides of Task List. With CFEclipse installed, you're ready to edit CFML files.

Like Flex Builder 3, CFEclipse provides a wizard for creating new projects. The server-side code for Task List is contained in {JBoss root}/tass.war/com/firemoss/tasks. Because ColdFusion uses the filesystem for its packaging scheme, instructing the wizard to create a new package in this directory creates a com.firemoss.tasks package.

Inside this package there is a ColdFusion component (the ColdFusion version of a class or object) named Task.cfc. This model of a task (Listing Six) is visible to the ColdFusion class loader as com.firemoss.tasks.model.Task. Because this is equivalent to the RemoteClass alias to which you earlier pointed your ActionScript 3.0 Task, any ActionScript 3.0 Task instances sent to ColdFusion are automatically turned into instances of the Task.cfc component. Inside the Tasks.cfc file, a similar alias annotation states that an instance of a ColdFusion Task sent to Flex should be marshalled into an instance of an ActionScript 3.0 Task.

<cfcomponent output="false" hint="DTO for a Task" alias="com.firemoss.tasks.model.Task">
<cfproperty name="id" type="string" hint="UUID of this task." />
<cfproperty name="task" type="string" hint="Name of this task,     e.g., ""Buy Milk""" />
<cfproperty name="complete" type="boolean" hint="Is this task      complete?" />
<!--- Initialize --->
<cfset this.id = "" />
<cfset this.task = "" />
<cfset this.complete = false />
</cfcomponent>

Listing Six

With this aliasing in place, when Task instances are sent back-and-forth between ColdFusion and the Flex application, properties declared in both Tasks.as and Tasks.cfc are automatically populated, thanks to a technology known as "Flash Remoting." Without this capability, you would need something like SOAP or XML/REST, and write code to parse XML.

With a model in place, the server-side components need a persistence mechanism. In a production environment, this would probably involve a relational database. With ColdFusion's flexibility and Java foundation, you have options for working with databases. You could hand-write SQL for persistence, use a native ColdFusion Object-Relational Mapping (ORM) framework such as Transfer, or employ a pure Java solution such as Hibernate.

Task List maintains a memory-resident list of Task instances, simulating the presence of a database. To enable future expansion to a true database, this knowledge is hidden inside of a Data Access Object pattern implementation. The ColdFusion interface com.firemoss.tasks.persistence.ITaskDAO is used to define methods such as list() and save(). A MockTaskDAO component then implements these methods using the memory-resident application scope provided by ColdFusion. Obviously, use of such global variables is strongly discouraged for production applications.

With a model and persistence mechanism implemented, the server must expose its functionality. All that's required is a Remote Façade Pattern implementation that's implemented as another ColdFusion component, TaskService.cfc, within /com/firemoss/tasks/service. This provides two coarse-grained methods corresponding to the high-level use cases within the application: listTasks() and saveTask().

The listTasks() method is simple, using MockTaskDAO to read the tasks. The saveTasks() method, however, must also perform real-time pushing of updated tasks to all clients currently running the application. Thanks to ColdFusion event gateways, this requires just four lines of code (Listing Seven). A ColdFusion structure (HashTable) is created and populated with the configured-by-convention destination of "ColdFusionGateway." A body consisting of the Task instance to push is also created and then dispatched to the appropriate event gateway instance with the sendGatewayMessage() function.

<!--- Notify client applications --->
<cfset taskMessage = structNew() />
<!--- Flex messaging destination to use: Matches <mx:Consumer /> tag        attribute --->
<cfset taskMessage.destination = "ColdFusionGateway" />
<cfset taskMessage.body = arguments.task />
<cfset sendGatewayMessage("taskGateway", taskMessage) />
Listing Seven

When this code is executed, the Flex application's Consumer tag receives the HashTable as a messaging object, invoking an appropriate event handler that modifies its collection of tasks.

Your application is now ready to run. Simply click the green Run arrow in Flex Builder 3 and the application executes. If there's an error in Task List, you can use the Eclipse-based ColdFusion Debugger (provided by ColdFusion 8) and the Flex Debugger (built into Flex Builder 3) to step through the code without ever leaving Eclipse.

Creating a Deployable WAR

When the application is debugged, you can create a deployable WAR of your application that compresses the application into a single file, much like a ZIP archive. To deploy a WAR to most Java application servers, the only installation step is to place the WAR file into the deployment directory.

When Flex Builder 3 compiles a Flex application, it creates a debug build. For production purposes, it provides an Export Release Build wizard, which lets you create an optimized Flash SWF file. To complete the tasks.war file, the Export Release Build wizard is used to build the application into /tasks.war, which contains files such as {JBoss root}/server/default/deploy/tasks.war/Tasks.html.

To create a distributable WAR of both the client and server applications, ColdFusion provides a wizard that's accessed through the ColdFusion administrator. The ColdFusion J2EE Archive wizard handles all of the building and configuration for you. Pointing it at the /tasks.war directory creates a single WAR file ready to be deployed to any compatible JEE server—no deployment scripts necessary and the Task List application is packaged as a WAR.

Conclusion

If you're still using HTML, JavaScript, complicated server deployments, and other technologies that don't "just work," try downloading the free Adobe Flex 3 SDK, a trial edition of Adobe Flex Builder 3 Professional, and the free developer edition of Adobe ColdFusion 8 to begin building better web applications with fewer headaches.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.