Issues Using Wirebox in CB4.

Hi All,

I’m having some issues trying to get Wirebox to inject a model from inside a model.

Basically, Model A does a call to Model B. All my models are by convention located in the new “models” folder. I have no issues injecting from a handler.

Inside of my config/Wirebox.cfc file I have my configure method set with the following mapping:

map(“correspondence”).to(“models.correspondence”);

I have no scope applied to this so it should be created as a “TRANSIENT” if my research is correct. As I did in my handlers I performed the annotation method:

property name=“correspondence” inject=“id:correspondence”; to match my alias set in the Wirebox binder or config file.

In my handlers i referenced it like so:
var objCorrespondence = getInstance(“correspondence”);

Everything works fine there.

In my model I get a slew of different responses:
if I leave the property annotation as stated earlier i get the following:

Injection Attempt 1 from Model A to Model B:
Annotation:
property name=“correspondence” inject=“id:correspondence”;

Call in the code:
var objCorrespondence = getInstance(“correspondence”);

Error Message Received:
Type: Injector.InstanceNotFoundException
Messages: Requested instance not found: ‘correspondence’ The instance could not be located in any declared scan location(s) () or full path location

Injection Attempt 2 from Model A to Model B:
Annotation:
property name=“correspondence” inject=“correspondence”;
Call in the code:
var objCorrespondence = getInstance(“correspondence”);

Removed the “id” in the annotation and added the “models” folder to the scanLocaions in config/Wirebox.cfc.

// Package scan locations
scanLocations = [“models”],

Reinited and I received the same error.

Injection Attempt 3 from Model A to Model B:
Annotation:
property name=“correspondence” inject=“correspondence”;

Call in the code:
var objCorrespondence = getInstance(“models.correspondence”);

Error Message Received:
Type: Expression
Messages: Variable GETINSTANCE is undefined.
Strangely, it says the Getintance method is not undefined now when I try using the direct model mapping.

Injection Attempt 4 from Model A to Model B: The last error lead to me to this. This method appears to be working.
Annotation:
property name=“correspondence” inject=“correspondence”;
Call in the code:
var objCorrespondence = application.wirebox.getInstance(“models.correspondence”); Is this now bypassing the annotation i have at the top of the model file.

Can anyone help me out on this? The model files are generally dumb in nature by design, i understand that piece. I just need some guidance if you could.

Referencing wirebox registered at the application level seems to work for me only if i go directly to the model listing and not through the alias I declared in the wirebox.cfc.

a little stuck. Also, is there a quick way to dump out all the aliases currently registered with Wirebox? ( Like the ones created asSingleton and asEagerInit(). )

Thanks!

You are injecting it correctly using:

property name=“correspondence” inject="correspondence”;

That means that WireBox will place it in the variables scope, you don’t need to call using a method.

variables.correspondence

Luis Majano
CEO
Ortus Solutions, Corp
www.ortussolutions.com
P/F: 1-888-557-8057
Direct: (909) 248-3408

ColdBox Platform: http://www.coldbox.org

ContentBox Platform: http://www.gocontentbox.org
Linked In: http://www.linkedin.com/pub/3/731/483

Social: twitter.com/ortussolutions | twitter.com/coldbox | twitter.com/lmajano | twitter.com/gocontentbox

Hi Luis,

If I understand you correctly. Once I use the cfproperty or property tag to inject a model into a handler or model… I should then be able to view those objects in the variables scope when the handler/model is called.

I put some some line breaks in my handler and placed my code on the debugger. I could only find one out of the three injections in that scope. The other two seemed to be ignored. In the line debugger i see them listed as property but they don’t appear to wire up.

Is there anything special I need to do to the handler/model? I must be missing something.

Just to note this system is on CF9 not sure if that has anything to do with it. Also, I never seem to experience these issues on another project using Railo and CB4.

I seem to remember Andrew Scott reporting some bugs in the step debugger that might affect that.

Also note, dependencies aren’t injected until AFTER the init() has been called. If you need to perform initialization that depends on injected variables, create an onDiComplete() method.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Hassan, I had intended to reply more thoroughly to your original message, but was out of town and then forgot.

> Inside of my config/Wirebox.cfc file I have my configure method set with the following mapping:

> map(“correspondence”).to(“models.correspondence”);

There’s nothing wrong with that per se, but it’s unnecessary since the default scan location is already the models folder, which means that model will be found automatically. No need to create a mapping-- it’s redundant.

> I have no scope applied to this so it should be created as a “TRANSIENT” if my research is correct.

Yes, IF you haven’t put any scope metadata inside the CFC itself. An example would be adding the “singleton” attribute to the component declaration.

> property name=“correspondence” inject=“id:correspondence”; to match my alias set in the Wirebox binder or config file.

We call them mapping names, not aliases, but regardless, what you have is fine. It’s also worth nothing the following properties are all the exact same functionality-wise:

property name=“correspondence” inject=“id:correspondence”;

property name=“correspondence” inject=“model:correspondence”;

property name=“correspondence” inject=“correspondence”;

> Injection Attempt 1 from Model A to Model B:

> var objCorrespondence = getInstance(“correspondence”);

> Requested instance not found: ‘correspondence’ The instance could not be located i

That error probably came from the property. Did you reinit first?

Also, getInstance() will not work in a model. That method is provided to “framework” files such as views, layouts, handlers, and interceptors via the framework super type, but you cannot call getInstance() in your models unless you have defined a getInstance() method.

> Removed the “id” in the annotation and added the “models” folder to the scanLocaions in config/Wirebox.cfc.

Neither of those changes should make any difference since the “id” bit is optional and “models” is the default scan location. Hard to say what the issues was. Perhaps a typo, or you had moved the CFC into a sub folder.

> Injection Attempt 3 from Model A to Model B:

> var objCorrespondence = getInstance(“models.correspondence”);

> Messages: Variable GETINSTANCE is undefined.

Again, you can’t call getInstance() in your model.

> Injection Attempt 4 from Model A to Model B:

> var objCorrespondence = application.wirebox.getInstance(“models.correspondence”);

That will work if you have scope registration enabled for WireBox, but is not recommended as it breaks encapsulation. If you want to access WireBox in a CFC, you should inject it.

property name=“wirebox” inject=“wirebox”;

If you need a transient, inject wirebox, and then call wirebox.getInstance().

> Referencing wirebox registered at the application level seems to work for me only if i go directly to the model listing and not through the alias I declared in the wirebox.cfc.

Sorry, I don’t understand what you mean by that. Whether you create an explicit mapping for a CFC, or reference it by name in the root of the models scan location, it’s still just going to be referenced by the name of the CFC.

> Also, is there a quick way to dump out all the aliases currently registered with Wirebox?

Yes, there is. Don’t be afraid to read through the API docs or, just open the code to WireBox (start with Injector.cfc) to look for clues.

Dump this out:

wirebox.getBinder().getMappings()

to see all the mappings that have been created. Note, adding scan locations will not add mappings up front. They are added the first time you ask for the model and WireBox finds it. That way, the “scan” only happens once. Using map().to(), mapPath(), or mapDirectory() however will create explicit mappings when the framework reinits whether or not the CFC is ever requested for building.

Thanks!

~Brad

Hi Brad,

You have helped immensely! Thank you again. The issue was that I didn’t know i had to reinit whenever a property was added to the handler or model. After I reinited, new properties they’re created with no problem. I can see them being created in the cf debugger.

I also injected wirebox into the models then called a transient using wirebox.getInstance(""); Thanks!

Lastly, the explicit mappings were created simply because we’re in the process of moving and reorganizing our codebase. For instance, the previous code we’re looking at has the following folder structure:

Models:

Form1: (folder)

formUtils.cfc

Form2: (folder)

formUtils.cfc

So to get the app working while we focused on a plan to refactor I simply added the following mappings because the cfc’s had the same name:
map(“form1Utils”).(models.form1.formUtils);
map(“form2Utils”).(models.form2.formUtils);

If I allowed Coldbox to map it I assume it would have been something like this in the property?
property name=“form1” inject=“models.form1.formUtils”;

Again, thank for you help! We’re up and running.

Ahh yes, even if the CFC being wired is new, WireBox caches the metadata for mappings for performance reasons, so a reinit is needed to reload everything and pick up the new property metadata.

> property name=“form1” inject=“models.form1.formUtils”;

Well that would work since WireBox falls back on full CFC path resolution, but with scan locations, it could actually just be:
property name=“form1” inject=“form1.formUtils”;

Because scan locations, are basically the “models convention location” and you can just do relative paths from within that folder.

Here’s something else you can do:
mapDirectory( ‘models’ );

/models/Form1/formUtils.cfc
component alias=“form1Utils” {

}

/models/Form2/formUtils.cfc
component alias=“form2Utils” {

}

WireBox will pick up the aliases and allow you to reference the mappings that way as well. WireBox will also try to create two “formUtils” mappings (the latter will overwrite the former) but you would just ignore them.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Awesome, makes perfect sense. I will try a few out and see what happens! Thanks again.

-Hassan