Another decorator question

0 views
Skip to first unread message

Tom McNeer

unread,
Feb 6, 2008, 4:32:14 PM2/6/08
to transf...@googlegroups.com
The other thread regarding decorators has moved well into the realm of new high-flying uses. My question is simpler, so I won't insert it into the middle of what's turned into a very interesting discussion.

Here's the thing: even after all the excellent explanations in that other thread, I'm still uncertain about when configure() runs, and whether to use it in certain instances.

Here's an abbreviated example:

I have a Case object (like a legal Case). There is an Attorney object which is related to it by a manytone tag in the Case object's definition.

Which means, of course, that there's no AttorneyID in the Case object definition, and thus no myCase.getAttorneyID() method (or "set," of course). It's myCase.getAttorney().getAttorneyID().

However, I am using Transfer Objects as Model-Glue event-beans. So it would be handy to have a setAttorneyID() method which would accept an AttorneyID passed from the form into the event.

That's simple enough to add to the Decorator. And that's my real need, so I'm happy.

    <cffunction name="setAttorneyID" access="public" returntype="void" output="false">
        <cfargument name="AttorneyID" type="numeric" required="true" />
        <cfset variables.AttorneyID = arguments.AttorneyID />
    </cffunction>

But as an exercise, I created a configure() method in my decorator, which contains the following:

<cfif getOriginalTransferObject().hasAttorney()>
      <cfset setAttorneyID(getOriginalTransferObject().getAttorney().getAttorneyID()) />
</cfif>

(And by the way, since I'm uncertain of the syntax, I've tried both getTransferObject() and getOriginalTransferObject(). Which is correct in this case?)

So I would expect that if the Case object is an existing Case, with an Attorney relationship, the AttorneyID would populate and be available with getAttorneyID(). However, when I create a Transfer Object with get("cases.case",caseID), then call getAttorneyID(), I get an error saying that variables.AttorneyID is not defined.

Am I doing this incorrectly? Is it a bad idea? Or is it simply that configure() runs when the object itself is created, but before it is populated with the data from the database?

--
Thanks,

Tom

Tom McNeer
MediumCool
http://www.mediumcool.com
1735 Johnson Road NE
Atlanta, GA 30306
404.589.0560

Brian Kotek

unread,
Feb 6, 2008, 4:37:18 PM2/6/08
to transf...@googlegroups.com
What if you add a getAttorneyID method to the decorator that does:

<cfset getOriginalTransferObject().getAttorney().getAttorneyID() />

?

Paul Marcotte

unread,
Feb 6, 2008, 4:43:19 PM2/6/08
to transf...@googlegroups.com
I do this all the time.  In fact, have a set method got the other way as well,

<cffunction name="setAttorneyID>
  <cfargument name="id" type="numeric" required="true">
  <cfset getTransferObject().setAttorney(getTransfer().get("partnership.Attorney",arguements.id)) />
</cffunction>

You won't need to use configure to set the AttorneyID, just decorate methods around the transfer object. :)

Paul
--
Paul Marcotte
Fancy Bread - in the heart or in the head?
http://www.fancybread.com

Tom McNeer

unread,
Feb 6, 2008, 5:01:11 PM2/6/08
to transf...@googlegroups.com
Brian and Paul,

On Feb 6, 2008 4:37 PM, Brian Kotek <bria...@gmail.com> wrote:
What if you add a getAttorneyID method to the decorator that does:

<cfset getOriginalTransferObject().getAttorney().getAttorneyID() />

I assume you meant:

<cfreturn getOriginalTransferObject().getAttorney().getAttorneyID() />

... but yes, that works. And I understand why.

But it still begs the question of why the original version didn't set the AttorneyID, or when the configure() method runs.

Paul, I understand that I don't need to use configure() to set the AttorneyID.  I'm just trying to understand how and when configure() can be used.

Don't misunderstand: I appreciate the advice from both of you. But this was just an example, meant to help me learn the operation of the configure() method. What I presented in the example is more of an exercise than a use case.

I'm also trying to understand the difference between getTransferObject() and getOriginalTransferObject() when used within a Decorator. Or for that matter, when used anywhere. (Yes, Mark, I've read the documentation. It's just still not getting through to me.)

Mark Mandel

unread,
Feb 6, 2008, 5:07:24 PM2/6/08
to transf...@googlegroups.com
Tom,

A few points here:

Looking here:
http://www.transfer-orm.com/transfer/documentation/decorators.html

You can see that getTransferObject() returns the Decorated Transfer Object.  There is an example available.

That being said, I can't see why you would need to access it directly in your decorator.  Simply 'getAttorny().getAttornyID()' - the method is made available to the Decorator.

On configure() to c/p paste from the documentation:
Overwriting configure() will be run when the object is first created.

So this is run when the object is first created, not populated.

Stupid question - but why set the variable in the CFC itself? why not just reference the composite object you have got?

Realistically, I'm not a big fan of this approach, as it 'smells' of your relational model, which is not something I would be advocating, you should probably be pushing for more of an ideal Object model.

Mark
--
E: mark....@gmail.com
W: www.compoundtheory.com

Mark Mandel

unread,
Feb 6, 2008, 5:22:18 PM2/6/08
to transf...@googlegroups.com
Tom,

getOriginalTransferObject() isn't documented... so why are you worrying about where to use it?

Again, the configure() method is run when the object is new() not when it is populated, so the attorney id wouldn't be set, as a new object would never have a composite.

Mark

Tom McNeer

unread,
Feb 6, 2008, 5:29:20 PM2/6/08
to transf...@googlegroups.com
Hi Mark,

On Feb 6, 2008 5:07 PM, Mark Mandel <mark....@gmail.com> wrote:
Looking here:
http://www.transfer-orm.com/transfer/documentation/decorators.html

You can see that getTransferObject() returns the Decorated Transfer Object.  There is an example available.

See, that's where I was getting confused. The Decorator page you refer to says:

"...you can use getTransferObject() to return the original TransferObject" -- not the Decorated Transfer Object.
 
On configure() to c/p paste from the documentation:
Overwriting configure() will be run when the object is first created.

So this is run when the object is first created, not populated.

Thanks. Yes, I read that. I just wanted to confirm my interpretation.
 
Stupid question - but why set the variable in the CFC itself? why not just reference the composite object you have got?

Realistically, I'm not a big fan of this approach, as it 'smells' of your relational model, which is not something I would be advocating, you should probably be pushing for more of an ideal Object model.

Absolutely true. I'm using the object relationships throughout my code. As I said, this example was an exercise to try to understand better how and when configure() works. Now that you've kindly confirmed that "created" means exactly that, I understand that you can't put anything in configure() that relies on using data from a populated object. In truth, that's most of what I was trying to understand.

Sorry if my example made you and the others think I was actually presenting code I was using. I appreciate your, Brian's, and Paul's attempts to help me solve a problem you thought I had. Occasionally (but not often) I do have a moment to spin up something to try to learn from it. That's all the example code was.

And as far as your question below goes:


getOriginalTransferObject() isn't documented... so why are you worrying about where to use it?

 
It was mentioned (I think) in the other current conversation in the group. I was just trying to understand the difference in the two methods so I would use them appropriately. And obviously, the answer is "don't use getOriginalTransferObject() at all."

Thanks again for a great tool. I'm just trying to learn how to use it properly. (Wouldn't want to put my eye out.) ;-)

Paul Marcotte

unread,
Feb 6, 2008, 5:35:25 PM2/6/08
to transf...@googlegroups.com
Tom,

My apologies for not reading your post clearly and bull-dogging you with my "smelly" decorator methods ideas. I use configure(), but not to act on existing methods or data, so I haven't run into situations where it didn't meet my needs.

Mark,

I'm a little puzzled, so if you can elucidate, I'd appreciate it.  The documentation referenced above says, " If you wish to have access to the TransferObject stored within the decorator, and any of its original generated methods, you can use getTransferObject() to return the original TransferObject".

If I look at the generated transfer definition files, I see two files for a given object.  One with an @ symbol, and another with a $ symbol.  If I have an Address property on my object, I can find the following method in the definition with the @ symbol.

<cffunction name="setAddress" access="public" returntype="void" default="void" hint="" output="false">
<cfargument name="Address" type="string" required="true" default="">
<cfscript>
getTransferObject().setAddress(arguments.Address);
</cfscript>
</cffunction>

This leads me to believe that definitions with the $ symbol are methods for the TransferObject, definitions with the @ are decorated methods and methods in my custom decorator can over-ride the methods in the @ symbol definitions.

Does that mean that there is more than one layer of decoration going on? 

Decorated layers....mmmm....cake.....

Paul

Tom McNeer

unread,
Feb 6, 2008, 5:57:56 PM2/6/08
to transf...@googlegroups.com
Paul,


On Feb 6, 2008 5:35 PM, Paul Marcotte <pmar...@gmail.com> wrote:
My apologies for not reading your post clearly and bull-dogging you with my "smelly" decorator methods ideas.

No apology needed. As I said, I appreciate any help in learning more. And the method was "smelly"; fortunately, it also wasn't real.

Or at least it was --- half-baked.

Paul Marcotte

unread,
Feb 6, 2008, 6:13:50 PM2/6/08
to transf...@googlegroups.com
Tom, I was talking about my code not yours.  ;)

For the record, I decorate methods that smell of the relational model to facilitate painless object data population, leaving it up to the transfer object to compose itself.  I get what Marks is saying though.  It's a practice a purist would poo-poo.  Whoa, things are really getting smelly now...

Paul

Mark Mandel

unread,
Feb 6, 2008, 6:24:01 PM2/6/08
to transf...@googlegroups.com

I'm a little puzzled, so if you can elucidate, I'd appreciate it.  The documentation referenced above says, " If you wish to have access to the TransferObject stored within the decorator, and any of its original generated methods, you can use getTransferObject() to return the original TransferObject".

If I look at the generated transfer definition files, I see two files for a given object.  One with an @ symbol, and another with a $ symbol.  If I have an Address property on my object, I can find the following method in the definition with the @ symbol.

<cffunction name="setAddress" access="public" returntype="void" default="void" hint="" output="false">
<cfargument name="Address" type="string" required="true" default="">
<cfscript>
getTransferObject().setAddress(arguments.Address);
</cfscript>
</cffunction>

Yup...
 


This leads me to believe that definitions with the $ symbol are methods for the TransferObject, definitions with the @ are decorated methods and methods in my custom decorator can over-ride the methods in the @ symbol definitions.

Yup, that is also correct
 


Does that mean that there is more than one layer of decoration going on? 

Nope. ;o)

You'll notice that the .transfer files are just UDFs, there arent' CFCs.

What is actually happens is multiple layers of method injection.

So the TransferObject cfc is created, and then the generated methods are injected onto it.

Then the decorator is wrapped around the TransferObject, and then it's methods are injected onto it, ignoring any methods that you may have overwritten.

That's pretty much it, but there are some other pieces in there for performance etc.

Mark

Paul Marcotte

unread,
Feb 6, 2008, 7:13:43 PM2/6/08
to transf...@googlegroups.com


On Feb 6, 2008 3:24 PM, Mark Mandel <mark....@gmail.com> wrote:

Does that mean that there is more than one layer of decoration going on? 

Nope. ;o)

You'll notice that the .transfer files are just UDFs, there arent' CFCs.

What is actually happens is multiple layers of method injection.

So the TransferObject cfc is created, and then the generated methods are injected onto it.

Then the decorator is wrapped around the TransferObject, and then it's methods are injected onto it, ignoring any methods that you may have overwritten.

That's pretty much it, but there are some other pieces in there for performance etc.


Thanks!  I probably didn't need to know that, but it helps.  ;)

Cheers,
Reply all
Reply to author
Forward
0 new messages