Transfer and Flex: Part 1

I started a project a couple of months ago that has and is going to continually have a very complex and growing architecture. The technology stack in place is Flex 3, Cairngorm 2.2, ColdFusion 8, ColdSpring, Transfer, and SQL Server 2005. This is my first Flex application that will be using Transfer to handle the database abstraction layer. Normally, I would use Brian Rinadi's Illudium PU-36 CFCGenerator to handle the initial generation of all my CFCs and from there would either modify the XSLT files or simply append to the generated CFCs as I saw fit.

The problem with this type of approach lies namely in the early stages of application design and development (especially since I traditionally don't go through a line of specs working on a solo project) when the database is going through many changes. Each time you make a change to the database, you either have to regenerate your files which will overwrite any changes you made, or you have to manually hand-code the database changes. On top of this, it doesn't take care of any of your table relationships as per a 3rd normal form database structure. You then have to design your own home-brew setup of such a system if you require it, or simply provide functions that return the structs/VOs to Flex as you need them by manually building up the hierarchical tree of the model.

For this project, I knew from the beginning that the database schema was going to be pretty complex and that it was also going to be going through changes as I developed and tried things out. I knew that I wanted to get Transfer to work with Flex. I had tried this once in the past and failed because I was designing Flex applications differently at that time. I now know better to design with a service layer in mind.

Although, it is not that easy either. There are actually quite a few steps involved when using Transfer to interact with your database and to return the right kind of objects back to Flex. Also, let me state, that I am talking about this in terms of using the AMF protocol with RemoteObjects between ColdFusion and Flex so that datatypes are appropriately and quickly translated.

This post will first introduce the Transfer ORM framework and why it is not a basic task to integrate it into your ColdFusion / Flex application. In the next part of this article, I will discuss the technical details of getting this all to work.

Transfer ORM framework

Visit project website

ORM, or Object-Relational Mapping, in simplistic terms is abstracting a representation of your data inside a database as objects in your application. An ORM framework does all of this abstraction semi-automatically by means of introspection to your database and generating the necessary files, or by a configuration file that describes the datatypes and the relationships of the tables to each other. Transfer falls into the latter category.

While some say that a fault of Transfer (esp when compared to a competing framework, Reactor) is that you have to write the table structure and it's relationships manually in an XML file. Whereas Reactor is a framework that reads the database metadata. At first, I thought this same thing and after working with Transfer later, have found it much better to be in control and to define the relationships myself. With this method I really feel like I have a much better understanding of what Transfer is creating when it generates it's objects. Plus when debugging your code it is easier to see what columns/fields are causing issues in your relationships.

The benefits of using Transfer over generating the CFCs yourself using tools like Brian Rinaldi's Illudium PU-36 CFCGenerator is that once you have defined your XML file, the actual creation of the CFCs is completely automatic. To give you an example, let's say you have a table in your database called Employee that has the following fields: employeeId, firstName, lastName, email. Once you have instantiated the TransferFactory, you simply call the object the you would any other VO, only you haven't previously written it:

<cfset firstName = variables.Transfer.get('employee', 1).getFirstName() />

Transfer.get() retrieves a specific Transfer object (which is defined in your Transfer XML) with a Primary Key ID of "1". Then it simply calls the generated "getFirstName()" method on that object and returns it to you. That's it! It is really simple.

This is hardly even skimming the surface of what Transfer does for you. Let's say that an employee can have multiple phone numbers on file that you store in a separate table called EmployeePhone. This is of course a One-to-Many relationship. Once you have simply defined this relationship in your Transfer XML you would then access the phone numbers this way:

<cfset emp = variables.Transfer.get('employee', 1) />
<cfset empPhoneArray = emp.getPhoneArray() />

From there you can simply loop through that array which in turn provides different EmployeePhone Transfer objects. You can configure in your XML whether that relationship will return an array or query. Notice that I mentioned it would return an array of Transfer Objects. This is where it gets tricky. The default return type of any relational object is typed as a Transfer Object. This is instantiated from the generic Transfer Object interface in the framework and is what all the relational object inherit from. However, you can change this by applying a decorator to any of your objects which will change the type of the object to the decorator path. The decorator will also allow you to add methods as well as change existing ones that the Transfer Object defines.

As you can see, Transfer can be very very powerful in your applications. It doesn't require very much setup time and configuration. As with most advanced concepts like this, it takes practice to really understand the underlying methodologies and to use them wisely in your application. Also, do not think that Transfer is simply a glorified code generator. Mark Mandel has spent a lot of time utilizing ColdFusion's unique strengths to truly make this a fast and effecient framework to keep your application at top speed.

That's it for now. Next time I will actually get more technical about the configuration file and start discussing how to prepare your CFC middle-tier for Flex consumption.

Related reading:

Microsoft Access encourages developer carelessness

After evaluating a problem that a teammate at work was having today with regards to importing data from a Microsoft Access database to a Microsoft SQL Server database, I came to the conclusion after solving that problem that Access allows a user to do things that may not be Kosher when it comes to proper programming.

I will admit, that when I first started out in dynamic web development, an Access database is all I had access to (please mind the unintentional pun). As most young developers, I did not have the money/knowledge/resources to develop using a higher end database. Microsoft Access was designed for the basic user in mind, and though it is capable of working with web applications I would not suggest using it for an application that is larger than the scope of your personal database needs ( i.e. DVD Catalog, Pet's Medical history etc.).

The issue at hand is my teammate has been recently converting an application within our organization to the new CLAF (Common Look and Feel). Our organization has also been converting all of the Access databases that are owned by its customers into SQL Server databases. With this, he was attempting to import the old Access database to a new Sql Server 2000 database. He ended up calling me because he was having so many problems. The application is a time tracking application that notifies the rest of the team when people are logged in. The original developer of the application created three columns In, Out, and TodaysDate. The In and Out fields are TimeDate datatypes but they only stored time data, not the date. The date of the entry was stored in TodaysDate which was the same datatypes as In and Out. Normally I leave well enough alone when it comes to the way people design their applications. But the issue was that my teammate spent a lot of time trying to figure out why the database was not transferring over. He gave me a call and I eventually figured out that the problem was that SQL Server was trying to import the In / Out data into the SQL Server database. In and Out only has time data and SQL Server does not allow for only the time data to be imported. What should have been done was that the date and time data should have been included in the In and Out columns and not had the TodaysDate column at all. Then the developer should have received the date information by parsing it from the In and Out fields. This also makes more sense because in the old way, if someone logged out the next it would break the application.

My point in all this ranting is that Access if at all possible should not be used for Internet application development. If you do choose to use, make sure you use it wisely. Again, I am not saying don't use Access cause if you don't have the resources to use Microsoft SQL Server or similar solution it is a decent solution.