Requirements      
Prerequisite knowledge Required products
Sample files
User level
The samples discussed in this article presume the reader possesses a high-level understanding of Adobe technologies (such as Flex and AIR) and of Adobe products (such as ColdFusion and LiveCycle Data Services ES).
Adobe ColdFusion Enterprise Edition (2016 release) (Download trial)
microblog_demo (783 KB)
Advanced

 

In this article, I will discuss how to use Adobe technologies to build an enterprise micro-blogging solution. My intent is to demonstrate that a full-fledged, enterprise-capable solution can be built using solely Adobe tools. Such a solution can overshadow existing comparable solutions on many levels, including security, convenience within the enterprise, and integration with other technologies.

This article does not explain step-by-step how to build a micro-blogging solution, but rather presents the framework and Adobe technologies that you can use to construct your own.

Note: For related information, you may also want to watch our recorded MAX 2009 session on Adobe TV: Vibes, Twitter, and enterprise microblogging (60:00).

 

Selecting criteria for the Adobe stack

 

There are several building blocks that make it easier to build a killer enterprise micro-blogging solution: data management, ORM, rock-solid enterprise scalability, and a cross-platform RIA desktop experience. Adobe ColdFusion 9, Adobe LiveCycle Data Services ES, and Adobe AIR combine to provide them all.

 

ColdFusion 9 Hibernate ORM features

ColdFusion 9 provides a solid and powerful application server. With the addition of Hibernate Object Relational Mapping (ORM) support, using ColdFusion as the service layer cuts the code needed to handle all the CRUD from 100+ lines across several ColdFusion Components (CFCs) to just a few lines.

ColdFusion 9 also comes with Flex/Flash remoting and integration, allowing the client Adobe AIR application to perform a mix of data service subscriptions and remoting calls to retrieve data. The ORM implementation in ColdFusion 9 simplifies object mapping. A prime use case for a micro-blogging solution is the concept of Groups and Users. Defining a Group persistent object with a one-to-many mapping to Users makes modifying the Group membership easy. Modifying the Users array contained in the Group object and calling EntitySave('Group') will handle all of the needed database transactions, including insert, delete, and modify operations.

 

LiveCycle Data Services ES managed publisher/subscriber model

Using the Adobe LiveCycle Data Services ES (2.6.1) data management capabilities and RTMP (Real Time Messaging Protocol) channel provides both a real-time subscriber/publisher model and a scalable enterprise model. With this technology, the system maintains persistent RTMP connections with the clients to provide real-time message delivery. LiveCycle Data Services ES in combination with AIR provides off-line synchronization support, allowing users to store messages locally for searching when offline.

 

Adobe AIR cross-platform desktop runtime

A huge part of any enterprise solution is cross-platform support. With both Mac and Linux gaining ground on Windows among workplace desktops, the most useful clients are deployable across all three operating systems (not to mention the various versions of each). Not only does Adobe AIR meet this objective, but the auto-update framework built into Adobe AIR also makes updating and managing application versions simple.

 

Setting up ColdFusion and LiveCycle Data Services ES

 

This section describes the ColdFusion and LiveCycle Data Services ES set-up, configuration, and application files.

 

Install ColdFusion and LiveCycle Data Services ES

Please refer to Adobe ColdFusion 9 Help for details on installing ColdFusion 9, and then follow the steps outlined for integrating LiveCycle Data Services ES 2.6.1 on ColdFusion 8 (it is the same process for ColdFusion 9).

After you have installed ColdFusion 9 and LiveCycle Data Services ES, you're ready to get started.

 

Configure LiveCycle Data Services ES

To use the data management capabilities in LiveCycle Data Services ES, you have to define a service destination in the data-management-config.xml file located in your {ColdFusionRoot}/wwwroot/WEB-INF/flex directory. Refer to the following example of a service destination:

 

<destination id="messageService"> <adapter ref="coldfusion-dao"/> <channels> <channel ref="cf-rtmp"/> </channels> <properties> <component>components.demo.MessageAssembler</component> <scope>request</scope> <metadata> <identity property="message_id"/> </metadata> <network> </network> <server> <fill-method> <use-fill-contains>false</use-fill-contains> <auto-refresh>true</auto-refresh> <ordered>false</ordered> </fill-method> </server> </properties> </destination>

 

Now consider the properties defined in it, from the top.

 

 

This specifies the destination with an id attribute. You use this id to reference the destination.

 

 

This refers to the adapter being used to serialize the data. Because this example uses integrated LiveCycle Data Services and ColdFusion, this property is set to coldfusion-dao. Adapters are defined in the first section of the data-management-config.xml file. There are other types of adapters (including Java and ActionScript object); for more information see Understanding data management adapters.

 

<component>components.demo.MessageAssembler</component>

 

This property specifies the CFC that LiveCycle Data Services ES will use to implement the CRUD functions (see Step 3: Create MessageAssembler.cfc for details). Essentially, this Assembler implements six basic functions: fill, doCreate, doUpdate, doDelete, sync, and get. When a collection that LiveCycle Data Services ES is managing (that is, monitoring for updates, new items, deletes, and so on) changes, it will look to this Assembler and call the necessary functions.

 

<destination id=…>
<adapter ref=…>
<channels> <channel ref=…> </channels>

 

This property defines the channel that will be used to communicate with the destination. These channels are defined in the services-config.xml file (found in the same folder as data-management-config.xml). This example uses cf-rtmp; make sure it is uncommented in the services-config.xml file.

 

<scope> </scope>

 

This defines the scope in which the request lives; possible values are application or request.

 

<metadata> <identity property="message_id"/> </metadata>

 

This property uniquely identifies the items in the database. In this example, message_id is the primary key reference in the database.

 

<server> <fill-method> … </server>

 

These are parameters to be passed when calling the fill method; the values used in the code are the defaults. For more details refer to the LiveCycleData Services documentation.

 

Set up the ColdFusion code

To take advantage of the ORM capabilities in ColdFusion 9there are a few things that need to be configured, including Application.cfc, theentity CFCs, and MessageAssembler.cfc.

Step 1: Edit Application.cfc

Add the following lines to your Application.cfc file:

 

<cfset this.name = "Demo Message Service" /> <cfset this.ormEnabled = "true" /> <cfset this.ormSettings = { Dialect="MySQLwithInnoDB",useDBForMapping=true,savemapping=false,logSQL=true } /> <cfset this.datasource = "Demo" />

 

This code does three things:

  • Enables ORM on a global level.
  • Specifies some specific ORM settings, importantly the Dialect. This code lets ORM know that it will be using a MySQL database to persist the data.
  • Defines the data source for ORM calls as Demo. Data sources are configured in the ColdFusion Administrator; refer to the ColdFusion documentation for more details.

Step 2: Set up the entity CFCs

In this example, there are two entity objects corresponding to two entity CFCs, Message.cfc and Dig.cfc. Messages are the main entities that contain the information about the message being sent such as the user, content, and posting date. Dig entities are entries of users who like or dislike the message, similar to a rating. One message can have multiple Dig entries related to it; you use ORM to define this relationship. These entities (which are similar to POJOs in the Java world) are simple value objects; to make them ORM enabled you need to add certain parameters.

In the Message.cfc, add the following parameters:

 

<cfcomponent persistent="true" table="message" entityname="Message">

 

  • Persistent="true" enables ORM functionality on this entity.
  • Table="message" maps the Entity to the corresponding database table.
  • EntityName="Message" defines the entity name used in ORM functions.

The Message entity defines several properties:

 

<cfproperty name="message_id" fieldtype="id" generator="identity" generated="always" unsavedvalue="0" />

 

This message_id property is a special property known as an identifier or id property. You specify fieldtype="id" to map a property to the primary key in the table. The values for generator and generated indicate how this property is generated. In this case, it is mapped to the primary key column in the Message table, so the MySQL database will always generate a value for it when it is written. (For more information, see the ColdFusion 9 documentation.) Finally, unsavedvalue="0" tells ORM how to determine if this entity has been saved to the database. When the code tells ORM to save a Message with a message_id value of 0, ORM will know to create a new entry instead of trying to update an existing one.

 

<cfproperty name="content" /> <cfproperty name="user_id" />

 

These properties are pretty standard; the name of the property corresponds to a column in the database table. If you want to map different column names to properties, you can add column="myContentColumnHere" in the <cfproperty> tag.

Finally, in the Message.cfc file there is a <cfproperty> tag with a one-to-many mapping.

 

<cfproperty remotingFetch="true" name="digs" cfc="Dig" fieldtype="one-to-many" collectiontype="array" fkcolumn="message_id" lazy="false" cascade="all" notnull="true"/>

 

This adds an array property to the Message entity containingDig entities. This relationship is well described in the ORM section of the ColdFusion9 documentation. Note that the remotingFetch propertymust be set to true for this, or else this property will not be returnedwith Flex remoting calls.

 

Step 3: Create MessageAssembler.cfc

There are six functions in the Assembler component forLiveCycle Data Services: sync, fill, get, doCreate, doUpdate,and doDelete.

The fill method is called to get the collection.Clients execute the fill method on a data service, which triggersLiveCycle Data Services ES to maintain a managed collection on the server side.When new objects are added, LiveCycle Data Services ES will determine if anyclient subscribed with fill parameters will need to be notified of this update.If one or more clients are supposed to see this item (based on the fillparameters), LiveCycle Data Services ES will dispatch an event to them andupdate them accordingly. If a client's fill parameters don't match the criteriafor viewing, it will not be notified.

Note: When two or more users perform a fill on a dataservice with the same fill parameters, LiveCycle Data Services ES will onlyneed to maintain one managed collection along with a reference for each userthat needs to be notified. This is handy information to have when buildingapplications with server-side memory consumption in mind.

The doCreate, doUpdate, and doDelete methods(as their names imply), create, update, and delete items. For example, if auser who is subscribed to a data service adds an item (for example, a message) from his or her managedcollection on the client side, LiveCycle Data Services ES calls the doCreate method and passes the item that was created.

 

Creating the Adobe AIR client

 

LiveCycle Data Services ES comes with three SWC files that you'll need to import to your project: airfds.swc, fds.swc, and fds_rb.swc. Personally, I like to copy these three SWC files to the libs folder in my AIR project.

Connecting to a data service from an AIR client is pretty easy after a few setup steps.

First, you create value objects (in this case, Message.as and Dig.as) in ActionScript, which have values that map to the corresponding CFC entities server side. Setting the [Managed] tag on the class indicates that this is an object that is managed by LiveCycle Data Services ES. The [RemoteClass(alias=..)] matches up the ActionScript object with the ColdFusion entity, so values are serialized correctly and the objects are easy to work with on the client side.

 

[Managed] [RemoteClass(alias="components.demo.Message")] Public class Message { … }

 

Next, you create the actual data service. The data servicerequires a ChannelSet, which it will use to establish the connection to theserver. The code to create it (for this article's server-sideconfiguration) is as follows:

 

//global vars: private var myDataService:DataService; private var myFillArrayCollection = new ArrayCollection(); //onCreationCompleteFunction: //create an RTMPChannel var myRTMPChannel:RTMPChannel = new RTMPChannel( "cf-rtmp","rtmp://myserver.hi:2048") //RTMPChannel requires the ID of the RTMP channel as defined in the services-config.xml and the full name of your server, plus the port that the rtmp channel is listening on, also defined in services-config.xml //create a new ChannelSet and add your newly created RTMP channel to it. var myChannelSet:ChannelSet = new ChannelSet(); myChannelSet.addChannel( myRTMPChannel ); //Now we create the actual DataService and assign the channelset to it myDataService = new DataService( "messageService" ) // messageService is the ID of the destination we setup in the data-management-config.xml earlier myDataService.channelSet = myChannelSet; myDataService.addEventListener(ResultEvent.RESULT, onDataServiceResult);// add a 'onDataServiceResult' function in later in the code, or comment this out. myDataService.fill( myFillArrayCollection ); //performs the 'fill' method defined in the MessageAssembler.cfc on the given DataService and returns the results into the 'myFillArrayCollection'

 

If all goes well, you should be able to put a break in your onDataServiceResult function and see the contents of myFillArrayCollection, which will be a series of Message objects with Dig objects in some of them.

Because your myFillArrayCollection was the target of the myDataService fill function it becomes a managed collection. Any item changes (adds, updates, deletes) to this array collection will trigger the corresponding LiveCycle Data Services ES function defined in the Assembler. For example, when the client creates a new Message object, sets some values in it, and then calls myFillArrayCollection.addItem(myNewMessage), it will trigger the doCreate function in the Assembler (which writes the object to the database using the ORM function EntitySave) and then update all clients that are also subscribed to this data service.

From here, you can add some custom item renders on a List control and you'll have a very rough (and simple) real-time message collaboration tool!

 

Where to go from here

This mix of Adobe technologies provides an enterprise stack that you can use to build a quality, comprehensive, enterprise micro-blogging solution. This enterprise stack enables the ongoing enhancement of both back-end services and front-end clients to enable rapid development of enterprise social networking solutions.

I encourage you to assemble your own solution to get a better understanding of the new features that ColdFusion 9 has to offer, the power of LiveCycle Data Services ES 2.6.1, and the convenience and cross-platform capabilities of AIR. When you do, I'm confident that you'll reduce twentieth-century communication within your enterprise and increase streamlined collaboration.

Also be sure to watch our recorded MAX 2009 session on Adobe TV: Vibes, Twitter, and enterprise microblogging (60:00).