Adding Todo Lists (Autowiring our Handler) - ColdBox Series Part 8c

As Luis stated in the comments section of my last post, we need to set up autowiring in our handler component. This is really cool stuff. I did not do this the first time around because my post was getting to long and because I wanted to demonstrate both ways of doing it.

What is autowiring?

When you are using object factories (like Lightwire and ColdSpring) in your ColdBox applications, you can set up dependency injection for handlers, plugins and interceptors. This is done using the Autowire Interceptor.

So what dependency do we have in our List.cfc handler? Here is what it looks like now:


<cfcomponent display="List Handlers" output="false" extends="coldbox.system.eventhandler">
    <cffunction name="addList" access="public" returntype="void" output="false">
        <cfargument name="Event" required="true" type="coldbox.system.beans.requestcontext" />
        
        <cfset event.setValue('xehDoit', 'list.doAddList') />
        <cfset event.setValue('btn', 'Add')>
        <cfset event.setView('listForm') />
    </cffunction>
    
    <cffunction name="doAddList" access="public" returntype="void" output="false">
        <cfargument name="Event" required="true" type="coldbox.system.beans.requestcontext" />
        
        <cfset var todoService = getPlugin("ioc").getBean("todoService") />
        
    </cffunction>
</cfcomponent>

Do you see the getPlugin() call in the doListAdd() handler? That is calling an object that the handler depends on to function properly. And if we were able to see into the future we would see that most, if not all, of the methods in this handler will also need that object. What a perfect opportunity for setting up autowiring. Wouldn't it be nice if we did not need to call this plugin for every method?


    <cfset var todoService = getPlugin("ioc").getBean("todoService") />

With autowiring, the todoService will be automatically injected into our variables scope (or another scope) and will always be available. So, first we need to go to our coldbox.xml.cfm file in our /config directory and set up the autowire interceptor.

Setting up autowiring

In the coldbox.xml.cfm file, find the <interceptors> tags and insert this block in between the beginning and end tags.


    <Interceptor class="coldbox.system.interceptors.autowire">
        <Property name="debugMode">true</Property>
        <Property name="completeDIMethodName">onDICOmplete</Property>
        <Property name="enableSetterInjection">false</Property>
    </Interceptor>

This tells ColdBox to use the autowire interceptor. It also sets up an optional method that will automatically be called after the dependency injection is completed. We won't be using that today. And the last property disables setter injection. With setter injection disabled, we only need a cfproperty tag to let ColdBox know what to insert. Honestly, I am not sure why we would want to turn it on. Maybe someone else knows and would like to enlighten us in the comments.

Now that we have modified the coldbox.xml.cfm file, we can change our handler to support autowiring. This is done with a bit of metadata.


<cfcomponent display="List Handlers" autowire="true" output="false" extends="coldbox.system.eventhandler">

Now ColdBox knows to autowire this handler, next we tell it what to inject. So we add a <cfproperty> tag in the pseudo-constructor area of the component. The pseudo-constructor area is in between the <cfrcomponent> tag and the first function.


    <cfproperty name="todoService" type="ioc" scope="variables" />

There. That was simple. Now the todoService (the "name" attribute must match the name as defined in ColdSpring or Lightwire) will automatically be placed into the variables scope when this handler is called. So we can get rid of the long getPlugin() call.

Conclusion

This may not seem like it is that helpful, but it is. When you consider that in a large application, your handlers may have several dependencies per handler, and each handler may have dozens of methods, it can make for much cleaner, easier to manage code.

Comments
Luis Majano's Gravatar Not only is it helpful jason, but some other benefits are:

1) Your object dependencies are all nicely laid out as properties on top. You do not need to scan the object for setters of any kind.
2) You do not need to create additional getters/setters if your object doesn't really need to create them. Why create them just for Dependency Injection? Objects should be shy!

Those are my main reasons to prefer DI via conventions.
# Posted By Luis Majano | 11/11/08 4:05 PM
Jason Dean's Gravatar @luis, thanks for the input. Good to know. I had not considered those things, but they make good sense.
# Posted By Jason Dean | 11/11/08 6:34 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner
Clicky Web Analytics