Setting up my Transfer Application

This post is more than 2 years old.

Following up on my blog entry from yesterday, today I'm going to talk about how to install Transfer and what my simple little application is going to look like.

Installation, like with most frameworks, consists of simply downloading a zip, extracting, and either placing the files under your application or creating a ColdFusion mapping. You can find download links here. This is no different than ColdSpring, Model-Glue, etc, but I really like to make use of ColdFusion 8's new ability to define mappings on the fly. So with that in mind, I placed Transfer in web root in a folder named transer1.1.

My application will be placed in a folder named empdirectory. I'm putting this right under web root as well. I'm not going to use Model-Glue or any other framework for this application as I want things to be as simple as possible. Let's first look at my Application.cfc file, specifically the mappings I'll use:

<cfset this.mappings["/empdir"] = getDirectoryFromPath(getCurrentTemplatePath())> <cfset this.mappings["/transfer"] = expandPath("../transfer1.1/")>

The first line defines a mapping named empdir. I'll use this as my root mapping for the application. This isn't something Transfer needs but is a convenience that will help in other places as well. Since Transfer is also directly below web root, I used ../transfer1.1 to point to the folder where I extracted the files. I don't know about you guys, but I freaking love being able to do mappings on the fly!

So now for the most important part. How do we add Transfer to our application? The installation docs tell us we begin by creating an instance of a CFC named TransferFactory. This CFC takes 3 main arguments when initialized. Let me show you how I created it within my application and then I'll describe each argument.

<cfset application.transferFactory = createObject("component", "transfer.TransferFactory").init( "/empdir/configs/datasource.xml", "/empdir/configs/transfer.xml", "/empdir/configs/definitions")>

The first argument tells Transfer where it will find datasource information. As you can imagine, since Transfer is abstracting interactions with your database, it needs to know which ColdFusion datasource to communicate with. I created a datasource.xml file and placed it within a config folder under my applications folder. My file has the following XML:

<datasource> <name>employeedirectory</name> <username></username> <password></password> </datasource>

Note! You must use the username and password keys even if you don't need them. I supplied this information in the ColdFusion DSN so I didn't need to supply it here.

The second argument is my Transfer Configuration file. This is a critical file. This file defines everything about how Transfer will abstract your database access and covers other items like caching as well. So basically, when I want Transfer to let me work with Employee objects, this is where I'll help define that relationship between the Employee business object and the database columns in the back end.

I am not going to cover the entire dialect of this XML file tonight! Tonight we will start simple. Here is the XML file as it stands in the first version of the application.

<transfer>
&lt;objectDefinitions&gt;
	
	&lt;object name="employee" table="employees"&gt;
		&lt;id name="id" type="numeric" /&gt;
		&lt;property name="firstName" type="string" /&gt;
		&lt;property name="lastName" type="string" /&gt;
		&lt;property name="dob" type="date" /&gt;
		&lt;property name="email" type="string" /&gt;
		&lt;property name="phone" type="string" /&gt;
	&lt;/object&gt;

&lt;/objectDefinitions&gt;

</transfer>

As you can probably guess, the objectDefinitions block defines what objects Transfer will recognize within my application. Right now my application has one object - employee. Because my database uses a different name for the table (employees) I have to tell Transfer what the table name is. My employee is made up of a few properties. I used some fairly generic things like first and last name, dob (date of birth), email and phone. I could have more of course, but again, I'm keeping things simple. Note that for each property I tell Transfer what type of property is being modeled. The only unique item here is the id tag. This tells Transfer what the primary key is for my database table.

So again - I'm not describing nearly every thing you can do in this file, but tonight, I want to keep it simple. (And I'll have complete zips at the end so you can see everything yourself!)

So finally, the last argument you pass to the factory is a folder name. This is a folder that Transfer will use for cached data and other generated files. I pointed to a definitions folder I created under config.

From this moment on, when it comes to Transfer, the main file I'll work with is the transfer.xml file. As I add new business object, define relationships, etc., I'll be workin gin there. I really have no need to touch datasource.xml file or worry about the definitions folder.

Ok, so now for the last item that may be confusing to folks. We just made an instance of the TransferFactory. But that isn't actually what you will use for most of your work. Instead, you will make use of a Transfer CFC that comes from the factory. In the Transfer docs you may see many examples that look like this:

<cfset foo = application.transferFactory.getTransfer().new("foo")>

This can get pretty tiring pretty quickly, so I simply created an application cached version of this component as well. Here is the entire onApplicationStart:

<cffunction name="onApplicationStart" returnType="boolean" output="false"> <cfset application.transferFactory = createObject("component", "transfer.TransferFactory").init( "/empdir/configs/datasource.xml", "/empdir/configs/transfer.xml", "/empdir/configs/definitions")>
&lt;cfset application.transfer = application.transferFactory.getTransfer()&gt;
&lt;cfreturn true&gt;

</cffunction>

While the Factory CFC does have functions we will use (and I'll be showing that in a second), it's the Transfer CFC itself that I'll spend most of my time in.

I'm a big fan of taking baby steps, so before I did anything else, I ran my application (using an empty index.cfm file) just to ensure nothing threw an error. Once that worked, I then used this code:

<cfoutput><p/>Transfer version: #application.transferFactory.getVersion()#</cfoutput>

This returned: Transfer version: 1.1

Wow, that was a lot of typing and I really haven't accomplished anything yet. But as I said, I like to go slow and ensure that the framework can even load without me screwing it up, and so far, it has.

Alright - so everyone with me so far? In the next blog entry I'll actually start using the Employee object with a very simple (and awesomely ugly - yes - I make web sites ugly) CRUD.

Download attached file.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Phillip Senn posted on 11/5/2008 at 8:47 AM

Transfer is change we need.

Comment 2 by Raymond Camden posted on 11/5/2008 at 8:53 AM

Nice... ;)

Comment 3 by Mat Evans posted on 11/5/2008 at 3:10 PM

Really looking forward to the rest of this series!

btw congrats on your new president, good choice :)

Comment 4 by Francois Levesque posted on 11/5/2008 at 5:26 PM

Great post, Ray. I think going through installing/using Transfer in baby steps like you're planning will be great for those interested in trying it out but afraid it's more complicated than it actually is.

Comment 5 by Geoff posted on 11/5/2008 at 7:55 PM

Ray. You said "Because my database uses a different name for the table (employees) I have to tell Transfer what the table name is."

Have you already made your database tabes? I thought Transfer would make the tables for you?

Unless I'm missing something...

Comment 6 by Raymond Camden posted on 11/5/2008 at 7:57 PM

Geoff, I kinda skipped over that - and I _knew_ that was a mistake, but I was hoping to get back to it tonight.

As a writer, I should have learned by now - trust my instincts.

No - Transfer will NOT make your tables for you. Hibernate does, and that is _extremely_ cool, but in this case, I had to make the table myself.

In tonight's blog entry, I'm discussing basic CRUD operations, and I'll be sure to cover this (not everyone reads the comments).

Cool?

Thanks for calling me out on that!

Comment 7 by Fred Anderson posted on 11/5/2008 at 8:35 PM

Great idea Ray, looking forward to the entire series.
If anyone is too impatient, like myself, to wait for the next post, here is the script for making the table in MySql.
-- ----------------------------
CREATE TABLE `employees` (
`id` int(11) default NULL,
`firstname` varchar(50) default NULL,
`lastname` varchar(50) default NULL,
`dob` date default NULL,
`email` varchar(255) default NULL,
`phone` varchar(50) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
-- ----------------------------

just make a db, create this table and then point a cf dsn named 'employeedirectory' at it.
Good luck.

Comment 8 by Aaron West posted on 11/5/2008 at 11:01 PM

@Geoff - I believe your question about whether Transfer creates tables or not (and the question behind the question) is one of the reasons Ray is starting this series.

Some folks don't believe Transfer is a true ORM since it will not create (or update) your database based on your objects. You can read more about the different perspectives on this topic in the following blog posts and comments:

Joe Rinehart:<br/>
http://firemoss.com/post.cf...
http://www.firemoss.com/pos...

Brian Kotek:<br/>
http://www.briankotek.com/b...

Comment 9 by Raymond Camden posted on 11/5/2008 at 11:28 PM

@AW: Well technically no. That's not why I started the series. If you see the first entry (see Related Entries above), I definitely talk about those articles by Joe and Brian, but my main intent here is to help others learn Transfer, and to help myself get a better understanding as well. (I'm most interested in the Event stuff. I have no idea how it's used so I'm looking forward to that.)

I think Joe's article is a good one. It certainly helped me. But this series main goal is more on the practical side.

Comment 10 by Chris posted on 11/6/2008 at 12:27 AM

Anyone having trouble running the code on Railo 3? I keep getting "invalid component definition, can't find transfer.TransferFactory" but my mappings look correct.

Comment 11 by Raymond Camden posted on 11/6/2008 at 12:31 AM

Right before the createObject, do a cfoutput on expandPath("/transfer"), and ensure that a) it points to the right file, and b) that folder has TransferFactory.cfc in it it.

Comment 12 by Chris posted on 11/6/2008 at 12:36 AM

Yup, checked both before and looks correct.

Comment 13 by Raymond Camden posted on 11/6/2008 at 12:38 AM

@Chris - if you get rid of my fancy this.mappings (well, don't get rid of it, remove the line for transfer) and make a 'real' CF mapping, does it work?

I'd also encourage you to post to the Railo listserv. They are typically fairly good with this kinda stuff.

Comment 14 by Chris posted on 11/6/2008 at 12:41 AM

Well, I removed the mappings and went to the railo admin and set the mappings there (A little different than CF8). Still nothing. I will try posting there too and post what I find.

Comment 15 by Pete posted on 11/12/2008 at 5:06 PM

Any help with this error?

The XMLFILEREADER argument passed to the init function is not of type transfer.com.io.XMLFileReader.

Comment 16 by Raymond Camden posted on 11/12/2008 at 5:10 PM

That's a new one on me. Maybe a typo in your XML? Unless you used the exact same XML from the zip. Worse comes to worse, try the mailing list: http://groups.google.com/gr...

Comment 17 by Pete posted on 11/12/2008 at 5:42 PM

I had a copy of the \Transfer folder in the employeedirectory. I removed it and everything is fine. Thanks