Tuesday, October 19, 2010

Using ColdFusion ORM with Flash Remoting in Flex via DTOs and Assemblers

ColdFusion 9 brought us a native implementation of Hibernate. ColdFusion has always been a wicked service tier, and extending CF ORM objects to Flex via remoting makes it even easier to connect CF and Flex.

NOTE: This information was originally explained to me over a bunch of conversations by Brian Kotek. Everything correct in this post can be attributed to Brian, and everything incorrect can be blamed on me ;).

There are a few reasons why utilizing data transfer objects (DTO) are a good idea:
  1. Reduce network overhead by only returning the data you need (BlazeDS - under the hood of remoting - has some issues with remotingfetch and lazy loading)
  2. Massage data to match the needs of the flex application's architecture (ordering arrays of children, concatenating strings, etc)
  3. Smaller footprint for serialization
A DTO is an an object that stores data. It is limited in that it knows how to do nothing else, but store data. DTOs are loaded up by an assembler (read about the dto assembler pattern). An object might have more than one assembler class depending on the method of access (such as remoting) or even the amount of data that needs loaded into an object for the present flex call. For example, one flex call might need a parent object with all related children, whereas another call might just need the parent object itself. In the latter case we could be returning a hundred objects when all we really need is a single string from the parent.

The following diagram shows a simplified workflow for reading data from a CF service tier from a Flex application:


The sample workflow shows a simple remoting call from the Flex application. The CF side receives the request in a singleton remoting proxy and uses CF ORM to load the requested object. The object is passed off to the assembler. The assembler knows how to assemble the DTO for this object. The proxy doesn't know anything about how to load the object or DTO. That functionality is injected into the proxy at runtime. When the DTO is passed back from the assembler it is returned to Flex. On the Flex side the AS3 DTO equivalent is populated and an assembler disassembles the AS3 DTO into the appropriate AS3 class.

The sample code below handles the ColdFusion side of the equation (the Flex side is the the same, but opposite). For our example we are requesting a Parent object with the specified ID via Flash Remoting. The call is received by our remoting proxy. Note that the proxy does not know how to create the Parent object or Parent DTO, but it knows where to get them via dependency injection. Take note that all of this would be even easier using if you allow ColdSpring to handle your objects ;)

RemotingProxy.cfc

1:  <cfcomponent displayname="RemotingProxy" hint="I am the RemotingProxy class.">  
2:      
3:    <!--- remote methods --->  
4:    <cffunction name="getParent" access="remote" returntype="parentDTO" output="false" displayname="getParent" hint="">    
5:      <cfargument name="parentID" type="string" required="true" />  
6:        
7:      <cfscript>  
8:        var parent = application.parentService.get(arguments.parentID);  
9:          
10:        return application.parentAssembler.assemble(parent);  
11:      </cfscript>  
12:        
13:    </cffunction>  
14:      
15:  </cfcomponent>  
The parent assembler's assemble() method takes the Parent object from ORM and maps it to the Parent DTO. The assembler then loads the children objects into the composition. It doesn't know how to assemble the ChildDTOs, but it has an instance of ChildAssembler injected into it at runtime that provides this functionality. Also note that there is a reference to the ProjectService. This is used when dissassembling. This would occur during a write operation triggered from the Flex application.

ParentAssembler.cfc

1:  component accessors="true" {  
2:    property ParentService parentService;  
3:    property ChildAssembler childAssembler;  
4:      
5:    public any function init (ParentService parentService, ChildAssembler childAssembler) {  
6:      setParentService(parentService);  
7:      setChildAssembler(childAssembler);  
8:        
9:      return this;  
10:    }  
11:      
12:    public ParentDTO function assemble (Parent parent) {  
13:      var dto = createObject('component', 'ParentDTO').init();  
14:        
15:      dto.id = parent.getID();  
16:      dto.title = parent.getTitle();  
17:        
18:      // add the children  
19:      aChildren = parent.getChildren();  
20:      for ( var i=1;i<=arrayLen(aChildren);i++ ) {  
21:        arrayAppend(dto.children, getChildAssembler().assemble(aChildren[i]));  
22:      }  
23:        
24:      return dto;  
25:    }  
26:      
27:    public Parent function disassemble (ParentDTO parentDTO) {  
28:        
29:      return ;  
30:    }  
31:  }  
The DTO stores all properties of the Parent class in public variables. You may choose to keep these variables private and provide accessors and mutators for access. The use of cfproperty here is for the purpose of self-documentation.

ParentDTO.cfc

1:  component alias="com.nictunney.dto.ParentDTO" {  
2:    
3:    property string id;  
4:    property string title;  
5:    property array children;  
6:      
7:    public any function init () {  
8:      this.id = '';  
9:      this.title = '';  
10:    
11:      this.children = [];  
12:        
13:      return this;  
14:    }  
15:  }  

The full code is available here. Hope this gets you started utilizing ColdFusion 9 ORM with your Flex applications.

1 comment:

  1. This is a nice beginner tutorial, do you have an example of the Flex portion as well?

    ReplyDelete