Amcom Home Page

 Building Business Objects with Transfer

So last time we had just finished an abstract class diagram for the business objects that we want to create for use in our Model. To write them by hand including the ability to save them to a database, would require you to write your own data persistence layer. Which would (should) include one (or more) of the multitude (DAO/Table Data Gateway/Gateway/Active Record/Data Mapper...) of design patterns dealing with persistence. They are all meant to solve essentially the same problem, separating the data access implementation from your business logic. Some of those patterns are quite different from each other and some are virtually identical. Implementing virtually any one of these strategies is a good start, but you will still need to deal with the assembly of the objects once you have the data.

Since the objects will to be composed of other objects (not just populated with data from one table), we have to come up with a way to assemble them. We have several options for doing this. We could just add the dependency logic to the data access tier (from above), we could have some kind of Factory (one or more) that would use the data access tier from above to populate the objects then assemble them with their dependencies satisfied, we could have our Service layer do the assembly directly, or we could use some combination of these. Personally, I'd prefer the Service layer be responsible for the job but delegate the work to Factories which in turn have dependencies on the data access tier (I like smaller task specific classes as opposed to larger kitchen sink classes).

Ok so I've gotten a little far a field... Let's get back to the point. For this demo app, we're not going to do any of that stuff manually... Cue choir music and shining golden lights...

Transfer will take care of virtually all of the above with very little work on our part. I'm exaggerating a little, we're still going to write gateway objects to promote encapsulation and loose coupling, but a lot of the heavy lifting will be done by Transfer.

I've revised the class diagram from last time a little. I've added some more classes to show why I chose to have a user object composed with a person object (a friend thought that approach was a little odd, so hopefully this clarifies the intent a little). I've also broken the Address class down a little, and this goes back to the point about the Object Model vs. Relational Model from the first post.

In a database with any degree of normalization, you will have lookup tables joined to primary tables by foreign key. Most ORMs (Transfer included) subtly encourage a one Table to one Object type of thinking. Transfer doesn't require that you work this way, but I think it does make it easy to fall into this type of design (which I admit I'll be falling into a little for this application). And in all fairness many applications work perfectly fine with 1:1 object table relationships. So in this new diagram I've labeled these "second class" classes (lookup tables) by shading them in a green box. Later in this series I'll refactor them out and turn them into properties, mainly for performance. But that will be once we have a service layer. So for now, this approach is a little less work and probably the most common way people will implement lookup type tables/objects in Transfer.




Ok so are we ready for some code? Almost here is a graphic showing the physical data model. I'm not going to into much detail about it, it's probably similar to a lot of DBs you've seen, partially normalized, pretty straight forward. The one thing I'll point out is that I've modelled PhoneNumber and Address differently, I have Person one to many PhoneNumber, but Address is more normalized and is a many to many via join table. I did this to show how both simple M2O and a more complex M2M type of relationship is done in Transfer. Ok now we're ready to start coding...

Transfer has a lot of good (but technical) documentation including a full API. But to get up and running all you really have to do is write up a configuration file. You define the objects, say what tables they represent, what properties they have and what column in the table they represent, what type the properties are, and then you define any relationships that objects have to each other.

Here is what the configuration of the Address object looks like:

<object name="Address" table="Address" decorator="com.amcom.demo.bo.Address">
 <id name="AddressId" type="numeric"/>
 <property name="StreetNumber" type="string" column="StreetNumber"/>
 <property name="Street" type="string" column="Street"/>
 <property name="Qualifier" type="string" column="Qualifier"/>
 <manytoone name="City">
  <link to="com.amcom.demo.bo.City" column="CityId"/>
 </manytoone>
 <manytoone name="ZipCode">
  <link to="com.amcom.demo.bo.ZipCode" column="ZipCodeId"/>
 </manytoone>
 <manytoone name="State">
  <link to="com.amcom.demo.bo.State" column="StateId"/>
 </manytoone>
</object>

<object name="AddressType" table="AddressType">
 <id name="AddressTypeId" type="numeric"/>
 <property name="AddressType" type="string" column="AddressType"/>
</object>

<object name="City" table="City">
 <id name="CityId" type="numeric"/>
 <property name="City" type="string" column="City"/>
</object>

<object name="State" table="State">
 <id name="StateId" type="numeric"/>
 <property name="StateCode" type="string" column="StateCode" nullable="false"/>
 <property name="State" type="string" column="State"/>
</object>

<object name="ZipCode" table="ZipCode">
 <id name="ZipCodeId" type="numeric"/>
 <property name="ZipCode" type="string" column="ZipCode" nullable="false"/>
</object>

I had trouble getting blogCFC to format my transfer xml! so this is unformatted sorry...

It's pretty self explanatory; we are mapping an Address object to the Address table (which could have a different name). We declare that we'll be using a decorator (more on that later), we map the columns in the table to properties in the object (again they could have a different name), and here is where it gets interesting. You'll notice we do not have properties defined for the foreign keys in the address table. There is no CityId, no ZipCodeId, not StateId. Instead we have declared that the Address object is composed of City, State and ZipCode objects. (These are those second class citizens I was talking about). We've done this using the manytoone tags to say Address has one City and it's linked to it by the foreign key CityId. So when we ask for an address, transfer will also retrieve the related city record and create a City object and compose it into the address object for us.

So now what is this decorator thing? Essentially it wraps itself around the generated transfer object, so that you can use all the functionality transfer creates for you, but also allows you to define any custom logic or behavior you want. You don't have to define decorators or use them, and I didn't define them for the "second class" objects, but without using the decorators you are basically just using the data access features of transfer. Which could be all that you need, but I hope to show how much more you can do by adding your own logic to your objects...

Well looks like I've rambled on for another chapters worth of densely worded text without actually writing any code... I promise the next post will be a lot of code at the end of which you'll get to see some results...

Comments
Terry Schmitt's Gravatar Good interesting series. I've been away from Transfer a while, but always find it interesting to see how others design their Transfer integration.

Oh... Your image links have an extra / in the path.
# Posted By Terry Schmitt | 6/24/08 10:02 AM
Oyun's Gravatar very thanks for you..
# Posted By Oyun | 11/15/08 4:06 AM

BlogCFC was created by Raymond Camden. This blog is running version 5.9.002. Contact Blog Owner