If You Use ColdSpring, Use Its Full Potential

I noticed a blog post recently called Building ColdFusion services with ColdSpring and Reactor, part 3 and wanted to comment about it.

A side note to Tom and Rachael (owners of that blog). You've decided to force visitors to register before they can comment. Which is quite a pain, but I tried to do it nevertheless. My password was never emailed to me. I requested another password, and it never arrived either. Please do something about this as it was pretty annoying to go through the process and still not be able to comment!

In this blog entry, and the others in the series, the writer is talking about using ColdSpring. This latest entry shows ColdSpring being used with Reactor. However, in my opinion they are only using ColdSpring for a portion of what it is really meant to provide.

The Reactor example has them injecting the Reactor factory (for some reason they have named it "ReactorGateway" which is a rather confusing choice) via a public setter. But then, other code is calling createGateway() on the Reactor factory to get a Gateway instance.

I think a better approach would be to use ColdSpring to get a Gateway instance and inject it for you. You can do this using the ColdSpring factory method support:

<bean id="UserManager" class="path.to.UserManager">
	<property name="UserGateway">
		<ref bean="UserGateway" />
	</property>
</bean>
<bean id="UserGateway" factory-bean="reactorFactory" factory-method="createGateway">
	<constructor-arg name="objectAlias">
		<value>User</value>
	</constructor-arg>
</bean>
<bean id="reactorFactory" class="reactor.reactorFactory">
	<constructor-arg name="configuration">
		<ref bean="reactorConfiguration" />
	</constructor-arg>
</bean>

		

This way, your manager doesn't have to know anything about the Reactor factory, or where this gateway is coming from. The same advice would apply to the previous entry in that blog series, where the Manager is making calls directly to the ColdSpring bean factory. Instead of calling getBean() for UserManager and Logger, inject these at object creation.

I think the only time I would access the ColdSpring factory directly is if I were creating a transient CFC. And even then, I'd probably use ColdSpring to inject a factory object into the necessary CFC and use that to create and return my new object. This is because the logic to correctly create and return a transient CFC (often a business object) ususally requires actual CFML code to perform (conditional statements, etc.)

Anyway, I just wanted to comment on this post and since I couldn't do it at Tom and Rachael's site I decided to do it here. If you're using ColdSpring, use it to its full potential. Don't stop at just injecting Reactor or ColdSpring into other components. Leverage the complete dependency management features of it. I think you'll find it makes your code more flexible.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
As an aside, having a bean container, such as Coldspring, inject itself into an object defeats the purpose.

Generally speaking, the goal of a bean container is:
1. configure and instantiate Singletons
2. inject Singleton references into other Singletons
3. do #1 and #2 in the right order to resolve dependencies automatically

Usually these Singletons are:
1. Immutable
2. Persisted for the lifetime of the application
3. Unaware of the bean container
4. Instantiate objects with mutable state
# Posted By Matthew Lesko | 5/21/07 6:29 PM
Actually there's nothing wrong with using ColdSpring to instantiate non-Singleton objects (what you are calling objects with "mutable state"). If you need complex factory logic then you'll have to create your own factory, but for simple object creation and dependency resolution one could certainly use ColdSpring (or LightWire for that matter) to create the object for you. In such a situation, injecting the bean factory into one of the Singletons so it can use it later is perfectly valid. I personally don't do it, but I think saying it defeats the purpose is going a bit too far.
# Posted By Brian | 5/21/07 6:36 PM
Hi there Brian.
Sorry you had problems registering, as I see from your own blog you ask for the exact same information as I do in order to deal with comment spam (but without an email confirmation step). It's a shame to enforce this pain on everyone because of a few idiots, but that's the way it is.
If you get in touch with details of your account, I will see what happened to it. If you are the relatively new user brian<3 numbers> at a popular webmail service provider, the email with the validation code was sent 9pm Monday. Maybe your provider bin'ed it as spam ?
On to the code then :-)
Yes, calling the injected Reactor Factory 'ReactorGateway' is confusing, I've altered that to make it clearer, cheers.
You make a valid point about injecting the Factory vs. injecting the gateway itself. We've found it more obvious to people getting started with OO to inject the Factory. The articles started being written many months ago, however, and things have moved on. I will try and cover some of the alternatives (such as your idea) and problems at the end of the series, when I've finished outlining one way in which you can build a tiered SOA.
That's one of the key themes of the series, actually. We took some ideas, and we built something. It might not be 100% right, it might not be always the best bits we've chosen to show you. But it's a good set of ideas (we think so anyway !), and helps give people a leg up into enterprise-class architecture with ColdFusion
@Matthew: I'm not sure why you say '[have] Coldspring inject itself into an object'. I certainly wouldn't normally advocate that, and don't see anything like that in Brian's article.
# Posted By Tom Chiverton | 5/23/07 4:42 AM
Hey Tom, thanks for checking on the account status. I did finally get back the email later that day (it was about 6 hours after I registered though), but it did actually get there. Yeah, I hate that I have to use stuff like captcha, but it's a good way to defeat most bots. You might think about adding captcha and removing the email sending/validation step, which would allow people to comment immediately. That was really the only thing that stopped me.

Don't worry, I've had many times where I wrote or did something and then looked back on it (even only a few days or weeks later) and wondered why I did something a certain way. I think the articles are very good, I just wanted to make sure that other readers (and you if you didn't know) were aware of the additional things ColdSpring can do. I highly doubt that most people are taking full advantage of it, since it can take some time to really "get" what a DI engine brings to the table. Whatever you do, keep those articles coming! The point of my response was definitely not to single you out or ding you for doing something "bad", but to expand on the topic to make sure others were aware of the additional capabilities of ColdSpring.
# Posted By Brian | 5/23/07 10:55 AM
I don't know if you are away, but LightWire injects itself into every object it manages. I was inclined to do the following in my service or manager:
<cffunction name="save" ...>
...
<cfset var bean = beanFactory.getBean("beanName")>
...
<cfreturn variables.DAO.save(bean)>
</cffunction>

Would this be a bad (inflexible) approach? My thought is that I could switch bean factory frameworks but my objects would always be dependent upon "a" framework.
# Posted By Aaron Roberson | 5/25/07 1:59 AM
I haven't really used LightWire before, but I would assume that for Singleton dependencies you'd still want to have it inject things like DAOs and Gateways at creation time. For transient objects, as I said, calling the bean factory is OK. It can be limiting though, because if your transient object has dynamic dependencies (for example, an Employee has a PayStrategy, but which type of PayStrategey to inject into it isn't known until runtime) it probably needs its own factory to make this determination. Of course, you can inject that custom Factory into your Singleton using LightWire (or ColdSpring). So, no, it's not an inflexible approach as long as your transient objects are fairly simple. If Peter reads this perhaps he can comment.
# Posted By Brian | 5/25/07 12:26 PM
Brian, when I subscribed to your blog, I got:
Line 623 Error:
'this.subscriber_email.value' is null or not an object.
I'm using IE6.
# Posted By Phillip senn | 6/8/07 1:50 PM
Huh, that's odd Philip. I tried it in Firefox and it worked correctly. Can you try again? I haven't made any changes to Rays blog code so I'm not sure why it would be failing on IE6 if it works on the other browsers.
# Posted By Brian | 6/8/07 1:53 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner