In this example, I have a model object called test.cfc
which has a dependency testService.cfc
.
test
has WireBox inject testService
through a property declaration. The object looks like this:
component {
property name="testService" inject="testService";
/**
* Constructor
*/
function init() {
// do something in the test service
testService.doSomething();
return this;
}
}
For reference, testService
has a single method called doSomething()
which dumps out some text:
component
singleton
{
/**
* Constructor
*/
function init() {
return this;
}
/**
* Do Something
*/
function doSomething() {
writeDump( "something" );
}
}
The problem is, WireBox doesn't seem to inject testService
until after the constructor init()
method fires. So, if I run this in my handler:
prc.test = wirebox.getInstance(
name = "test"
);
I get the following error message: Error building: test -> Variable TESTSERVICE is undefined.. DSL: , Path: models.test
Just for sanity sake, if I modify test
so that testService
gets referenced after the object is constructed, everything works fine. The problem seems to be isolated to constructor methods.
How can I make sure my dependencies can be referenced in my object constructor methods? Thanks for your assistance!
When a class requires an instance of a Dependency, you can supply that Dependency through the class's constructor, enabling it to store the reference for future use. Constructor Injection is the act of statically defining the list of required Dependencies by specifying them as parameters to the class's constructor.
Constructor Injection is the most common form of Dependency Injection. Constructor Injection is the act of statically defining the list of required dependencies by specifying them as parameters to the class's constructor.
Constructor Injection Dependency Injection is done by supplying the DEPENDENCY through the class's constructor when creating the instance of that class. The injected component can be used anywhere within the class. Recommended to use when the injected dependency, you are using across the class methods.
Types of Dependency Injection The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.
Due to the order of construction, you can't use property or setter injections in the init()
method. Instead, you can access them in the onDIComplete()
method. I realized the WireBox docs only had a passing reference to this, so I have added this excerpt:
https://wirebox.ortusbooks.com/usage/injection-dsl/id-model-empty-namespace#cfc-instantiation-order
CFC Building happens in this order.
createObject()
init()
method is called (if it exists), passing any constructor args onDIComplete()
method is called (if it exists)So the proper version of your CFC would be as follows:
component {
property name="testService" inject="testService";
/**
* Constructor
*/
function init() {
return this;
}
/**
* Called after property and setter injections are processed
*/
function onDIComplete() {
// do something in the test service
testService.doSomething();
}
}
Note, it would also be acceptable to switch to constructor injection, but my personal preference is property injection due to the reduced boilerplate of needing to receive the argument and persist it locally.
https://wirebox.ortusbooks.com/usage/wirebox-injector/injection-idioms
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With