Specifying tag attributes in a structure

This post is more than 2 years old.

Yesterday I was reading an article on Ben Forta's blog, Look, No Datasource, where he described how in ColdFusion 9, we can specify a default datasource at the application level that can then be used with all tags that use a datasource attribute. So instead of doing:

<cfquery name="getShots" datasource="#application.dsn#">

we can instead just do:

<cfquery name="getShots">

This is cool and all, but a reader commented that it would be nice if we could also supply default mail settings at the server level. I agree with him, it would be nice. Things like datasources, mail settings, etc, are typically high level things that individual tags should not need to worry about.

It occurred to me that he may not be aware of a feature, added in ColdFusion 8, which kind of allows for this right now. For a long time custom tags have supported an attributeCollection argument. This is a structure that acts like passed in arguments. So if a custom tag takes two arguments, num1 and num2, I could actually pass them in like so:

<cfset s = {num1="2",num2="67"}> <cf_foo attributeCollection="#s#">

That's not a great example as it didn't save me any keystrokes, but I think you get the idea. ColdFusion 8 simply expanded this to built in tags. So taking the reader's comment about mail, you could, if you wanted, do this in your Application.cfc file:

<cfset application.mail = {server="127.0.0.1",username="mail",password="pass"}>

and then pass it to your cfmail tags:

<cfmail to="some@where.com" from="admin@foo.com" subject="Your Email" attributeCollection="#application.mail#"> foo </cfmail>

Ok, so again, there isn't a huge savings in keystrokes, but it does allow you to change your mail tags from one central structure. Mail server doesn't require a password anymore? Just remove it from the struct. Want to supply a failto attribute? Add it to the struct and every cfmail tag uses the struct will be updated.

I've got to be honest and say that I've not yet used this in production (mainly because I keep forgetting about it!) but it's pretty powerful stuff. Anyone out there using it?

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 todd sharp posted on 6/22/2009 at 6:41 AM

I use it a bit, but not for the purpose you're demonstrating. Instead I use it as a more elegant way to handle conditional attributes. Example:

<cfset m = structNew() />
<cfset m.to = "address@mail.com" />
<cfif iWantACopy>
<cfset m.cc = "me@my.com" />
</cfif>
<cfmail attributeCollection="#m#">ray is a jedi</cfmail>

Comment 2 by Paul posted on 6/22/2009 at 6:58 AM

Handy for those of us using shared hosting, didn't know about it.

Comment 3 by Raymond Camden posted on 6/22/2009 at 6:58 AM

Ah yeah, that's a good one. You could image:

<cfif devServer>
cc to me
</cfif>

Comment 4 by Dale Fraser posted on 6/22/2009 at 8:46 AM

You can already control the mail settings at a server level in Administrator.

We do this always, and never specify mail server etc on the <CFMAIL tag

Comment 5 by salvatore fusto posted on 6/22/2009 at 11:30 AM

i'm used to enclose the cfmail tag in a cfc, init'ed with some attributes whose default values are the dafaults and call a sendmail(...) method to send emails.
salvatore

Comment 6 by Jody Fitzpatrick posted on 6/22/2009 at 2:22 PM

Hey Ray

I have a question about SoZo Hosting if you know anything about them.

1.) Are the reliable?
2.) Do you think they can support 10,000+ active users at the same time?

I assume that you would recommend them being that you have a banner linking to their site.

If you are not sure it's okay... Just wondering, and once I order I will make sure I click on your banner so you can get the sale lead... you taught me a lot an really helped me with the auto refresh div.

P.S

Could your Captcha get any simplier?

Comment 7 by Robert Haddan posted on 6/22/2009 at 7:22 PM

I use attribute collections extensively so that I can call tags via cfscript that don't have native cfscript support. Lately I've been mixing a lot of CF functionality with Java functionality, so being able to write everything in cfscript makes my code a lot easier to read.

Comment 8 by Steven Esser posted on 6/22/2009 at 7:33 PM

I guess it can be handy at times to not have to declare the datasource at all times, but I also know of applications where you rather want to keep that option: multiple databases, multiple datasources!
Happens from time to time to my applications that there is need to use two datasources. Then I suppose that you will have to use the datasource argument at all cfqueries.

For cfmail I don't make use of the server settings as I have set that on server level. I just have to keep specifying from and to's etc but I suppose you could write an easy function that checks for debug level or something so that I receive the message instead of the emailaddress meant for the application.

Comment 9 by todd sharp posted on 6/22/2009 at 7:50 PM

@Steven:

As it's been said, the default datasource (this.datasource) can be overridden at the tag level. The reason they added this feature is for ORM (Hibernate) integration. There needed to be a way for CF to know which datasource it was dealing with behind the scenes, so this.datasource was added to specify a default datasource.

(Per Adam Lehman at our UG tour meeting last week)

Comment 10 by Steven Esser posted on 6/22/2009 at 8:51 PM

@todd sharp: Can ORM's such as Hibernate and Transfer not work with multiple datasources? Or was it just a generally 'wanted' feature in this case.

Comment 11 by todd sharp posted on 6/22/2009 at 9:13 PM

@Steven - To be honest, I'm not sure the answer to that. Maybe Ray knows - he's travelling today if I remember correctly so let's see what he says later.

Comment 12 by Raymond Camden posted on 6/22/2009 at 11:26 PM

Afaik, Transfer is one DSN only. Not sure about Hibernate. To be honest, this doesn't concern me too much. In the 15 years I've been in dev, I think I've had 2 clients who needed multiple, and even then, the second one was used maybe 10% of the time, so this new CF9 feature will still be pretty useful in cases where you might have multiple DSNs in play.

Comment 13 by Raymond Camden posted on 6/23/2009 at 12:06 AM

Jody, this is a bit off topic. Can you ping me directly via my contact form?

Comment 14 by Sean Corfield posted on 6/23/2009 at 6:25 AM

@Steven, ORMs operate on a single data source because the syntax tends to be:

obj = orm.load(objectID);

... do stuff to obj ...

obj.save(); // or orm.save(obj);

So the data source is bound into the ORM essentially at initialization time.

With Transfer, you can have multiple Transfer factory instances, one per data source, if you want but, like Ray says, most applications have one main transactional data source and perhaps a separate reporting data source (for which you would not use ORM).

I suspect it would make the Hibernate integration more difficult to use if there had to be some way to have separate instances per data source. Based on what Adobe has shown of Hibernate integration, it looks like they've spent a lot of time on making it very easy to use.

Comment 15 by Gary Funk posted on 6/23/2009 at 6:39 AM

I think only the government uses more than one datasource. In my office, our main CF server connects to two MySQL servers and one DB2 server on an AS400, and one other datasource on our FECS server. The two main sources are the DR2 and one of the MySQL servers. That makes up about 85% with the DB2 coming in at about 35%.

Comment 16 by todd sharp posted on 6/23/2009 at 6:49 AM

Is that liberal math? 85%+35% != 100%....

Comment 17 by Gary Funk posted on 6/23/2009 at 8:28 AM

No, of the 85%, 35% is DB2

Comment 18 by todd sharp posted on 6/23/2009 at 4:52 PM

@Gary - It was a joke ;)

Comment 19 by Gary Funk posted on 6/23/2009 at 5:20 PM

You're telling me. All these servers and connections. Just so we can know when it's time to go to lunch and take our breaks.