Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

HowToUseCairngormIntegration

How to Use the Cairngorm Integration Library (Requires Parsley)

Contents

Summary

The integration library provides utilities to loosely-couple concerns of the communication with external environments with other client side architectural layers. Aside from sending and retrieving data, it also offers structures to manage global error handling, conflict resolution, and offers presentation components access progress and error information in a loosely coupled way. Supported are currently RPC, data management using LCDS, and LocalConnection. In the current version of the IntegrationParsley and IntegrationDMS libraries are dependent on Parsley. The Integration library containing the IDataCache utility does not depend on the Parsley framework but uses the Spicelib utility library for reflection on metadata. You can use IDataCache with any IoC framework.

As in previous versions of the Cairngorm MVC implementation, Cairngorm still recommends to encapsulate operations in Commands. Previous versions of the Integration library contained Parsley extensions to create Commands and react to their responses. Parsley 2.1 introduced a native Command implementation inspired by this version. We recommend to use the native Parsley extension going forward and have removed the Cairngorm version. We are delighted that Parsley has improved upon the approach. Power of open source.

IDataCache - Using RPC Securely

One drawback of using RPC instead of Data Management provided by LiveCycle Data Services is that every remote service can return different object references for the same Data Transfer Object object.

For example, if a user creates a new Contact object in the InsyncBasic sample application, saves it and later searches for it using the a remote search service, the search service might return a different object reference of the same Contact. One solution to overcome this limitation is to ensure that the Flex client only ever keeps one object reference for a Contact of a specified unique ID. LiveCycle Data Services provides this out of the box via the "Highlander Principle". IDataCache helps achieving this with using RPC at the expense of understanding the concept and writing this additional code.

The first service that saves an object needs to add the client side object reference to the cache using the updateItem method and update the properties from the object reference received from the remote service. In InsyncBasic , the SaveContactCommand achieves performs this operation:

[CommandResult]
public function updateContact(savedContact:Contact, request:ContactEvent):void
{
    cache.updateItem(request.contact, savedContact);
}

All remote services manipulating Contact objects need to update the IDataCache instance. The SearchContactsCommand needs to synchronize a collection:

[CommandResult]
public function onResult(items:IList, request:ContactEvent):void
{
    contacts.addContacts(cache.synchronize(items));
}

and the RemoveContactCommand needs to clear the Contact object from the IDataCache cache:

[CommandResult]
public function removeFromCache(items:IList, request:ContactEvent):void
{
    contacts.removeContact(request.contact);
    cache.clearItem(request.contact);
}

LiveCycle Data Services

The Parsley dependent IntegrationDMS library allows developers to configure objects with LiveCycle Data Managment 3.x features in a loosely coupled fashion. This library contains Parsley object definitions, which can annotate objects with metadata, MXML, XML and ActionScript.

IsCommitRequired

DataService.commitRequired indicates when managed objects have changed and contain uncommitted changes. Often, presentation components such as Presentation Models are interested to listen and i.e. offer controls such as Buttons to bind to it. The IsCommitRequired annotation can be used to separate the infrastructural DataService component from the presentation component.

[Bindable]
[IsCommitRequired(service="myDataService")]
public var isCommitRequired:Boolean

:::xml
<s:Button label="Save" enabled="{isCommitRequired}" />
DataServiceConflict & GlobalDataServiceConflict

LiveCycle Data Management provides an out-of-the-box conflict management mechanism. DataServiceConflict and GlobalDataServiceConflict subscribe to the appropiate events of one or many DataServices definitions and allow a more dedicated objects to listen.

The DataServiceConflict annotation listens to one specific DataService while the GlobalDataServiceConflict listens to all DataService defintions defined in your application Context. The latter can be useful for setting up global conflict handling rules.

The method must have one parameter of type mx.data.Conflict. If a DataService contains more than one Conflict, the method is going to be called consecutively for each conflict.

[DataServiceConflict(service="myDataService")]
public function conflictHandler(conflict:Conflict):void
{
    conflict.acceptServer();
}

OR

[GlobalDataServiceConflict]
public function conflictHandler(conflict:Conflict):void
{
    conflict.acceptServer();
}
DataServiceResult & GlobalDataServiceResult

Decorating a method with one of these two annotations provides the ability to handle a result without having to add a responder to the DataService definition. The GlobalDataServiceResult metadata can be used to handle results from all DataService definitions defined in your application Context.

[DataServiceResult(service="myDataService")]
public function myDataServiceResultHandler(result:ResultEvent):void
{
    ...
}

OR

[GlobalDataServiceResult]
public function globalResultHandler(result:ResultEvent):void
{
    ...
}
DataServiceFault & GlobalDataServiceFault

Decorating a method with one of these two annotations provide the ability to handle a fault without having to add a responder to the DataService definition.

The GlobalDataServiceFault annotation can be used to handle all faults from all DataService definition defined in your application Context.

[DataServiceFault(service="myDataService")]
public function myDataServiceFaultHandler(fault:DataServiceFaultEvent):void
{
    ...
}

OR

[GlobalDataServiceFault]
public function globalFaultHandler(fault:DataServiceFaultEvent):void
{
    ...
}

 

LocalConnection

The LocalConnection feature is a simple utility for publish and subscribe messaging between different Flash applications. It externalizes the configuration of LocalConnection settings and injects either a producer or a consumer into the the participating components.

Check out the LocalConnection example in IntegrationTest. Run the message producing application and the message consuming application.

To configure this extension, add the CairngormIntegrationSupport to your Context Builder.

<spicefactory:ContextBuilder>
    <cairngorm:CairngormIntegrationSupport/>
    <spicefactory:FlexConfig type="{ ConsumerContext }"/>
</spicefactory:ContextBuilder>

The external configuration can be defined in your context:
for the producer:

<!-- INTEGRATION LAYER -->
<flashnet:LocalConnection id="localConnection"/>

<localconnection:ProducerSettings id="producerSettings"
                                  connectionName="textCopyConnection"
                                  handlerMethodName="handleTextInput"/>
<Object id="producerDelegate"
        type="{ ProducerDelegate }">
    <ConstructorArgs>
        <ObjectRef idRef="localConnection"/>
        <ObjectRef idRef="producerSettings"/>
    </ConstructorArgs>
</Object>

and for the consumer:

<!-- INTEGRATION LAYER -->
<flashnet:LocalConnection id="localConnection"/>

<localconnection:ConsumerSettings id="consumerSettings"
                                  connectionName="textCopyConnection"
                                  domainName="*"
                                  allowInsecureDomain="true"/>
<Object id="consumerDelegate"
        type="{ ConsumerDelegate }">
    <ConstructorArgs>
        <ObjectRef idRef="localConnection"/>
        <ObjectRef idRef="consumerSettings"/>
    </ConstructorArgs>
</Object>

The IProducerDelegate or IConsumerDelegate can then be injected into any component that needs LocalConnection connectivity. The consumer can use the SubscribeToLocalConnection metadata in order to get the content from the producer:

[Bindable]
[SubscribeToLocalConnection(service="consumerDelegate")]
public var text:String;

[Inject]
public var delegate:IConsumerDelegate;

This restricts the participating components to the typical APIs needed while communicating and keeps configuration settings externalized.

### Cairngorm 3 - [ Home ][1] - [ Guidelines ][3] - [ Tools ][4] - [ Libraries Downloads ][2]
### Cairngorm 2 - [ Home ][5] - [ Framework Downloads ][6] - [ Eclipse Plugin ][7]
### Project - [ Source ][8] - [ Bug Database ][9] - [ Submitting a Patch ][10] - [ Developer Documentation ][11] - [ Forums ][12] - [ License ][13]