[[Dashboard | << Back to Dashboard ]] | << Interceptors Viewer
{|align="right"
| __TOC__
|}
= Autowire Interceptor =
== Introduction ==
The autowire interceptor is a great tool to use when using ColdBox's Model Integration, object factories like ColdSpring or LightWire or the ColdBox Cache. This interceptor will inject dependencies into the following ColdBox objects:
* Plugins
* Handlers
* Interceptors
If you would like to autowire any other type of object on demand you can use the BeanFactory plugin to accomplish this. Just for your information, the autowire interceptor USES the BeanFactory plugin to do all of its dependency injections. You can see all of its methods by visiting the [http://www.coldbox.org/api CFC API]
What are dependencies? Dependencies are objects that are created by the ColdBox Model Integration, object factories, objects that have been placed into the ColdBox Cache or even application settings. Overall, object dependencies can be anything that the object at hand needs in order to operate. Thus, the goal of the autowire interceptor is to unobtrusively describe your object's dependencies and inject them for you. You can use the autowire interceptor to inject dependencies from various sources according to our Dependency DSL (Domain Specific Language):
'''Note for Applications Built Prior to ColdBox 3.0M6:''' Prior to ColdBox 3.0M6, the DSL supported a ''type="model"'' annotation for cfproperty tags. Going forward, you will need to use ''inject="model"''. This change was made to prevent the hijacking of the ''type'' attribute for the cfproperty tag.
// The following will not work in ColdBox 3+
// Change the "type" attribute to "inject"
== Dependencies DSL ==
We have created a nice DSL for dependency injection that is used by using '''cfproperty''' and common setter methods. Not only does the cfproperty types apply to model objects but to anything that is autowired in ColdBox: plugins, handlers, interceptors, ioc produced beans, and on demand autowiring. Below is a chart of what you can use in both cfproperty tags and setter methods:
'''CFPROPERTY'''
* '''name''' : The name of the property to be injected
* '''type''' : The type of property to inject using our DSL (see chart below)
* '''scope''' : Into which scope to inject (Default is variables scope)
'''Types DSL'''
{| cellpadding=?5?, class="tablelisting"
! '''Type''' !! '''Description'''
|-
|| ioc || Get the named ioc bean and inject it. Name comes from the cfproperty name or setter name
|-
|| ioc:BeanName || Get the ioc bean according to Bean Name in DSL
|-
|| ocm || Get the name key from the ColdBox cache and inject it. Name comes from the cfproperty name or argument name
|-
|| ocm:ObjectKey || Get the object from the ColdBox cache according to DSL object key.
|-
|| model || Get a model with the same name or alias as defined in the cfproperty name="{name}" attribute. Name comes from the cfproperty name or setter name
|-
|| model:{name} || Same as above but it will get the {name} model object from the DSL and inject it.
|-
|| model:{name}:{method} || Get the {name} model object, call the {method} and inject the results
|-
|| webservice:{alias} || Get a webservice object using an {alias} that matches in your coldbox.xml
|-
|| coldbox || Get the coldbox controller
|-
|| coldbox:setting:{setting} || Get the {setting} setting and inject it
|-
|| coldbox:plugin:{plugin} || Get the {plugin} plugin and inject it
|-
|| coldbox:myPlugin:{MyPlugin} || Get the {!MyPlugin} custom plugin and inject it
|-
|| coldbox:datasource:{alias} || Get the datasource bean according to {alias}
|-
|| coldbox:configBean || get the config bean object and inject it
|-
|| coldbox:mailsettingsbean || get the mail settings bean and inject it
|-
|| coldbox:loaderService || get the loader service
|-
|| coldbox:requestService || get the request service
|-
|| coldbox:debuggerService|| get the debugger service
|-
|| coldbox:pluginService || get the plugin service
|-
|| coldbox:handlerService || get the handler service
|-
|| coldbox:interceptorService || get the interceptor service
|-
|| coldbox:moduleService || Get a reference to the ColdBox Module Service
|-
|| coldbox:interceptor:{name} || Get a reference of a named interceptor
|-
|| coldbox:cacheManager || get the cache manager
|-
|| coldbox:fwConfigBean || Get a configuration bean object with ColdBox settings instead of Application settings
|-
|| coldbox:fwSetting:{setting} || Get a setting from the ColdBox settings instead of the Application settings
|-
|| entityService || Inject a ''BaseORMService'' object for usage as a generic service layer
|-
|| entityService:{entity} || Inject a ''VirtualEntityService'' object for usage as a service layer based off the name of the entity passed in.
|-
|| javaLoader:{class} || Create an object from the [[Plugins:JavaLoader| JavaLoader]] plugin and its set of loaded java libraries
|-
|| logbox || Get a reference to the application's LogBox instance
|-
|| logbox:root || Get a reference to the root logger
|-
|| logbox:logger:{category name} || Get a reference to a named logger by its category name
|}
=== cfproperty Dependencies ===
So if an object needs dependencies after creation (usually the case), then just use our good old friend ''cfproperty'' to demarcate or annotate what needs to be injected. The good thing again, is we just rely on unobtrusive metadata to define what needs to be injected and it can be documented!! Ahh how I love that! Below is a very complex example:
That is so nice. We can use this DSL to inject almost anything into our objects. This approach of injection by annotation is our prefered method of dependency injection due to the fact that we can easily document it, easily see the dependencies once we open our components and it is easy to maintain. Below we learn about our counterparts, setter injection.
=== Setter Dependencies ===
You can easily use the mentioned DSL to wire up objects via setter injection instead of cfproperty injections. All you have to do is place a marker in the setter function in order to describe the dependency. The default attribute is called: '''_wireme'''. But what is setter injection? Setter injection is a way to inject objects/data to your desired/target objects by means of creating a setter method. A setter method is a simple method that starts with the word '''set'''. Below are some examples:
setUserService()
setManager()
setSetting()
setConfigBean()
As you can see from above, they all start with the word '''set''' and then they have a name. This name is usually the name of the object that you want to inject or set in your target object. This interceptor will first get a list of all the methods in the target object that start with '''set''' and try to find matches according to our DSL or defaults. So a simple example would be the following:
As you can see, you use the setter function marker: '''_wireme''' to tell the bean factory how to wire up the argument or setter method. Now, if you do not like my default marker, then choose your own. Just create a new setting in your coldbox.xml.cfm named: '''beanfactory_dslMarker'''.
//Then use the wireit marker:
As you can see from the samples above, wiring up setter methods is fairly easy and very descriptive. You are also not relying on inherited functionality or conflicting code, it is purely metadata that can be ignored if using another factory other than ColdBox. Other interesting aspects of setter injections are the following:
* Your setter method access types can be ''private'' if you so desire it. The interceptor and bean factory will now how to go around this. Remember that objects are shy, if you don't want it exposed, then set it as private.
* If you do not use a marker then the bean factory will do the following:
** Determine if you are using ColdSpring or LightWire?
*** Yes, then the default type is '''ioc'''
*** No, then the default type is '''model''' or model integration.
Now that we have learned about all the dependency injections and DSL we can move on and see how to configure our interceptor.
== 1. Configure the interceptor ==
The way to configure the autowire interceptor is via your configuration file. Look below for the sample:
trueonDICompletetrue
That's it!! So let's go over it. We first declare the autowire interceptor and we set some of the properties discussed below.
{|cellpadding="5", class="tablelisting"
! '''Property''' !! '''Type''' !! '''Default''' !! '''Required''' !! '''Description'''
|-
|| '''debugMode''' || boolean || false || false || Whether to use the logging facilities on successful/failed injections.
|-
|| '''completeDIMethodName''' || string || onDiComplete || false || This takes in the name of a method to fire on the injected object after all dependencies have been injected. This is incredible useful when you need to configure an object right after injections. It uses the ''onDiComplete'' convention, but you can use your own.
|-
|| '''enableSetterInjection''' || boolean || true || false || Determines whether you will use setter injection alongside cfproperty metadata injections or not.
|}
== 2. autowire metadata ==
The next step is to add a new property to the '''cfcomponent''' tag of the objects you would like to have auto wiring turned on. Simple as that.
'''autowire={boolean}'''
This simple property tells the framework that this object (plugin,interceptor or handler) needs to have dependencies injected into it. Please note that if you use the bean factory for on demand autowiring, you can disable the check for this metadata argument.
== 3. Metadata overrides ==
You can override two autowiring properties on a per-object basis by creating two attributes in your cfcomponent tag:
* '''autowire_stopRecursion''' : The class path of when to stop recursion for this particular object.
* '''autowire_setterInjection''' : Whether to use setter injection or disable it for this particular object.
Version 2.6.2 and above only
== 4. Dependencies ==
Now that you have declared that the component will be autowired, its time to create or describe which dependencies this object needs. We discovered our dependency DSL above so let's use it.
//Setter methods
So to recap, we declared the autowire interceptor in our configuration file, we added the autowire metadata to our cfcomponent tag and we added our cfproperty tags or our setter methods. An important aspect to notice is that the setter method has an access of '''private'''. You can leave this as private and the autowire interceptor will still be able to use it. Well, you can be done if you want, the last step is optional.
== 5. Complete DI Method Name ==
This step is completely optional and only used if you declared it in your config file and you created the appropriate method on your object. What this feature means, is that you can create a method on your object that has the same name as you declared it in your config. The ColdBox default is '''onDIComplete'''. So if this method is detected in your object, then ColdBox will execute it '''AFTER''' all dependencies have been injected in to the object. This is great for configuring an object once we know all dependencies have been injected.
== Conclusion ==
So there you go. Simple as 1-2-3-4 well and 5 if you are guru status! Very simple and easy to use.