model inject model dependency and ocm

63 views
Skip to first unread message

chris hough

unread,
Feb 7, 2012, 9:56:26 AM2/7/12
to ColdBox Platform
I have a bunch of code to paste, so I am going to try to set this up
pseudo code style. here is the layout of what I have that is throwing
the error:

Model A
Model B

Model A
Inject Ocm
Inject Model B
Call Method in B

Model B
Inject Ocm

when model a tries to inject model b and model b has an ocm injection,
I am getting an undefined error on the ocm injection variable

this is the function that errors in model b when it's called via the
model injection from model A

<cffunction name="qUserLevels" access="public" returntype="query"
output="false">
<cfargument name="LevelID" type="numeric" required="false"
default="0">
<cfargument name="HasMenu" type="numeric" required="false"
default="1">
<cfscript>
var qUserLevels=Instance.DataUserLevels;
var qUserLevelsOut=[];
</cfscript>
<CFQUERY NAME="qUserLevelsOut" dbtype="query">
Select LevelID,TextDesc
From qUserLevels
Where 0=0
<cfif IsNumeric(Arguments.LevelID) And Arguments.LevelID GT 0>
And LevelID = <cfqueryparam value="#Arguments.LevelID#" CFSQLType
= 'CF_SQL_NUMERIC'>
</cfif>
<cfif IsNumeric(Arguments.HasMenu) And Arguments.HasMenu GT 0>
And HasMenu >= <cfqueryparam value="#Arguments.HasMenu#" CFSQLType
= 'CF_SQL_NUMERIC'>
</cfif>
</CFQUERY>
<cfscript>
return qUserLevelsOut;
</cfscript>
</cffunction>

model a:
<cfproperty name="Permissions"inject="Model" scope="Instance"/>

the function call:

var qPermissions=Instance.Permissions.qUserLevels(HasMenu=1);

any tips or pointers? can this be done or should I use the
controllers to pass in the model dependencies?

br...@bradwood.com

unread,
Feb 7, 2012, 11:20:03 AM2/7/12
to col...@googlegroups.com
1)  How are you injecting your ocm dependency?  i.e.  Property annotations, WireBox config mappings, manually retrieving it from WireBox on init?
2) Where in your component are you trying to use it.  i.e.  init() is called before DI is complete so you can't use dependencies there.  That's what onDIComplete() is for.

Also, what version of ColdBox are you on and what is your DI engine? (legacy Bean factory, WireBox, ColdSpring, LightWire, etc)

Thanks!

~Brad
--
You received this message because you are subscribed to the Google Groups "ColdBox Platform" group.
To post to this group, send email to col...@googlegroups.com
To unsubscribe from this group, send email to coldbox-u...@googlegroups.com
For more options, visit this group at http://groups-beta.google.com/group/coldbox
For News, visit http://blog.coldbox.org
For Documentation, visit http://wiki.coldbox.org

chris hough

unread,
Feb 7, 2012, 11:26:16 AM2/7/12
to ColdBox Platform
I am using "<cfproperty name="DataUserLevels" inject="Ocm"
scope="Instance"/>"

to inject them on top, running cb 3.1, adobe cf8, I am using it after
the init() in side of the method.
> To post to this group, send email toco...@googlegroups.com
> To unsubscribe from this group, send email tocoldbox-...@googlegroups.com

br...@bradwood.com

unread,
Feb 7, 2012, 11:33:31 AM2/7/12
to col...@googlegroups.com
Exactly where is the ocm undefined error happening.  In Model A or Model B?  in other words, is it that Model A can't find the ocm or can Model B not find the ocm?

Can you confirm that injection is working in general for those objects?  Perhaps enable some WireBox debug level logging and make sure there are no issues putting the dependencies in there.

Thanks!

~Brad

chris hough

unread,
Feb 7, 2012, 11:35:38 AM2/7/12
to ColdBox Platform
It is happening in model B. If I remove the call to the injected OCM
Instance variable and call the method directly it works.

Here is the top of model b:

<cfcomponent name="Permissions"
extends="cfcRetailHub.model.ApplicationModelHelper" output="false">
<!------------------------------------------- CONSTRUCTOR
---------------------------------------------->

<cfproperty name="Dsn" inject="Coldbox:Setting:Datasources"
scope="Instance"/>
<cfproperty name="DataUserLevels" inject="Ocm" scope="Instance"/>

<cffunction name="init" output="false" returntype="Permissions">
<cfreturn this>
</cffunction>

<!------------------------------------------- OCM : PUBLIC
---------------------------------------------------->

<cffunction name="DataUserLevels" access="public" returntype="query"
output="false">
<cfscript>
var AppLevels=UserLevels();
return AppLevels;
</cfscript>
</cffunction>

<!--- ---------------------------------------- PUBLIC
---------------------------------------------------->
top of model a:

<cfcomponent name="Menu"
extends="cfcRetailHub.model.ApplicationModelHelper" output="false">
<!--- ---------------------------------------- CONSTRUCTOR
---------------------------------------------->
<cfproperty name="SessionStorage"
inject="Coldbox:Plugin:SessionStorage" scope="Instance"/>
<cfproperty name="DataNav" inject="Ocm" scope="Instance"/>
<cfproperty name="Permissions"inject="Model" scope="Instance"/>


<cffunction name="init" output="false" returntype="Menu">
<cfreturn this>
</cffunction>

<!------------------------------------------- OCM : PUBLIC
---------------------------------------------------->

<cffunction name="DataNav" access="public" returntype="struct"
output="false">
<cfscript>
var DataNav=StructNew();
DataNav.navRoutes=navRoutes();
DataNav.navRouteConditions=navRouteConditions();
DataNav.navRoutesByLevel=navRoutesByLevel();

return DataNav;
</cfscript>
</cffunction>

<!--- ---------------------------------------- PUBLIC
---------------------------------------------------->

<cffunction name="sGetNav" access="public" returntype="struct"
output="false">
<cfscript>
var sGetNav=StructNew();
sGetNav=Instance.DataNav;

return sGetNav;
</cfscript>
</cffunction>
> > To post to this group, send emailto...@googlegroups.com
> > To unsubscribe from this group, send emailtocoldbo...@googlegroups.com

br...@bradwood.com

unread,
Feb 7, 2012, 11:57:50 AM2/7/12
to col...@googlegroups.com
Yeah, I'm not sure.  I'll admit, I'm having troubles following the flow of execution.

Can you show your method in menu that is calling the method in permissions that is erroring?

When you say "If I remove the call to the injected OCM Instance variable and call the method directly it works." do you mean when you remove the reference to instance.DataUserLevels in the Permissions component? 

Also, I know you are injecting your properties into "instance", but it's rather confusing to have methods and instance vars with the same name.  Did you try injecting them with a different name just to see if that changes anything.


Chris Hough

unread,
Feb 7, 2012, 12:04:59 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
Here are the full files:

Menu.cfc
Permissions.cfc

br...@bradwood.com

unread,
Feb 7, 2012, 12:13:50 PM2/7/12
to col...@googlegroups.com
One other thing, are DataUserLevels and DataNav eternal objects in the cache?  If you are reinitting, make sure they are put in the cache prior to trying to inject them.

Chris Hough

unread,
Feb 7, 2012, 12:20:26 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
here is the snippet relative to the ocm, it's in the main handler

<cffunction name="onAppInit" returntype="void" output="false">
<cfargument name="event" required="true">
<cfscript>
//cache global data queries
var DataCompany = getModel('Company').DataCompany();
var DataMall = getModel('Mall').DataMall();
var DataStates = getModel('Information').DataStates();
var DataUserLevels = getModel('Permissions').DataUserLevels();
var DataNav = getModel('Menu').DataNav();
//Place in cache indefinitely until application reinitializes.
getColdBoxOCM().set('DataCompany',DataCompany,0);
getColdBoxOCM().set('DataMall',DataMall,0);
getColdBoxOCM().set('DataStates',DataStates,0);
getColdBoxOCM().set('DataUserLevels',DataUserLevels,0);
getColdBoxOCM().set('DataNav',DataNav,0);
</cfscript>
</cffunction>

Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 12:26:03 PM2/7/12
to col...@googlegroups.com
Thanks for sending the full files.  Let me see if I have this straight.  My understanding is that menu has permissions injected into it.  Then menu.navRoutesByLevel() is called which, in turn, calls the Instance.Permissions.qUserLevel().  Then qUserLevels() errors because it can't find Instance.DataUserLevels, which you currently have commented out and replaced with a direct call to UserLevels()
 which I can only assume is used to populate DataUserLevels in the cache.

So firstly, how and when in your application lifecycle is DataUserLevels placed in the cache, and what is its expiration?
What happens if you ignore menu and just call Permissions.qUserLevel() directly from a test page somewhere?
Also, I'm not sure if it matters, but are menu and permissions transient objects?

Thanks!

~Brad
--
You received this message because you are subscribed to the Google Groups "ColdBox Platform" group.
To post to this group, send email to col...@googlegroups.com
To unsubscribe from this group, send email to coldbox-u...@googlegroups.com
For more options, visit this group at http://groups-beta.google.com/group/coldbox
For News, visit http://blog.coldbox.org
For Documentation, visit http://wiki.coldbox.org



i think this will be far easier

did this help?

Chris Hough

Chris Hough

unread,
Feb 7, 2012, 12:28:30 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
transient objects?

I add the OCM values inside the main handler that runs before anything else executes, at least I thought it was supposed to work like that.

Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 12:37:22 PM2/7/12
to Chris Hough, col...@googlegroups.com
Not the objects in cache, the actual menu and permission CFCs.  Are they singleton objects that only exist once, or are there many instances of them created (and injected) over the course of your application life cycle?

Chris Hough

unread,
Feb 7, 2012, 12:39:03 PM2/7/12
to col...@googlegroups.com
they are injected, rather will be injected in various handlers at different times. 

Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 12:51:49 PM2/7/12
to col...@googlegroups.com
That doesn't answer the question, but unless you are declaring the mappings in your WireBox config as .asSingleton() I'll assume they are transient.  i.e.  if you inject menu into two different handlers, each handler has a separate instance of the menu object.

No matter, that was really just a side question. 
Did you try calling Permissions.qUserLevel() directly from a test page somewhere?

Also, you could try catch the error, and dump/abort out the instance/variables scope to see what exists at the time that it is erroring.

Chris Hough

unread,
Feb 7, 2012, 12:53:31 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
to avoid the confusion, those are 2 models talking talking to one another, not handlers.  

yes, the query works on its own, it only errors when I attempt to use the inject OCM variable.  


Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 2:05:07 PM2/7/12
to col...@googlegroups.com
> to avoid the confusion, those are 2 models talking talking to one another, not handlers.  

Yes I know-- I was just trying pin-point if the ocm injection happened once when the app started up (i.e. menu and permissions were singletons) or if it happened over and over throughout the life of the app each time a new menu and permission object was created. 

> yes, the query works on its own, it only errors when I attempt to use the inject OCM variable.  

Sorry, not what I meant.  Does the Permissions.qUserLevel() method "see" the Instance.DataUserLevels variable when it is called directly in a test view or handler?  You original post seemed to indicate that the broken behavior in Permissions.qUserLevel() was only present when it it was called from the menu object.

Also, to back up a bit, what fires the onAppInit() method? 

~Brad

Chris Hough

unread,
Feb 7, 2012, 2:45:32 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
Does the Permissions.qUserLevel() method "see" the Instance.DataUserLevels variable when it is called directly in a test view or handler? 

yes, it works as expected

what fires the onAppInit() method? 

my understanding is the framework calls that when the application is reinitialized.  is that incorrect?

Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 4:37:37 PM2/7/12
to Chris Hough, col...@googlegroups.com
> my understanding is the framework calls that when the application is reinitialized.  is that incorrect?

It depends on the applicationStartHandler setting in your config.  If it is set to "main.onAppInit" then it probably gets called.

Did you try turning on the WireBox debugging via LogBox to try and see what is happening when the permission object is injected (and autowired)?
What about try/catching the error and dumping out the contents of "variables"?

Thanks!

~Brad
-------- Original Message --------
Subject: Re: [coldbox:13743] Re: model inject model dependency and ocm
From: Chris Hough <chris...@gmail.com>

Chris Hough

unread,
Feb 7, 2012, 4:56:53 PM2/7/12
to <brad@bradwood.com>, col...@googlegroups.com
this is really weird, it appears to be working now.  yes I was reinit the framework each time, but it was never working.  

I restarted the server and bam it is working now.  seems odd.  can models inject models, or should i use handlers only?

Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 5:01:24 PM2/7/12
to col...@googlegroups.com
Anything can pretty much inject anything.  Please welcome your new Wirebox overlord.

Glad to hear it seems to be working for now.

Chris Hough

unread,
Feb 7, 2012, 6:08:37 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
HA, just when I said that it borked again.  geez.  

I am not sure if I should move the injection out completely or what....

here is the dump:


Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 6:22:21 PM2/7/12
to ColdBox List
After the error can you look in the CacheBox cache manager and see if that object is still in the cache?


~Brad
-------- Original Message --------
Subject: Re: [coldbox:13754] model inject model dependency and ocm
From: Chris Hough <chris...@gmail.com>
Date: Tue, February 07, 2012 5:08 pm
To: col...@googlegroups.com, br...@bradwood.com

HA, just when I said that it borked again.  geez.  

I am not sure if I should move the injection out completely or what....

here is the dump:


Chris Hough

Chris Hough

unread,
Feb 7, 2012, 6:28:40 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
If I use this around the block to test:

<cftry>
<cfscript>
//var qUserLevels=UserLevels();
qUserLevels=Instance.DataUserLevels;
qUserLevelsOut=[];
</cfscript>
<cfcatch type="any">
<cfdump var="#variables#" expand="false">
<cfaborT>
</cfcatch>
</cftry>



Chris Hough

br...@bradwood.com

unread,
Feb 7, 2012, 7:43:30 PM2/7/12
to col...@googlegroups.com
What does the dump show when it errors?  

You may need to turn debug mode on in your config for the cache panel to show.

~Brad

Sent from my HTC on the Now Network from Sprint!

Chris Hough

unread,
Feb 7, 2012, 7:47:13 PM2/7/12
to col...@googlegroups.com, br...@bradwood.com
it just shows standard cf debug:


yes, debug mode is set to true

If I go switch all this back to not use the OCM injecting I get the debug panels at the bottom of the screen as usual.  

thank you so much for your help btw.  thoughts?

Chris Hough

Chris Hough

unread,
Feb 8, 2012, 9:59:14 AM2/8/12
to Chris Hough, col...@googlegroups.com, br...@bradwood.com
Anyone have an thoughts on this issue?  should I move the OCM items somewhere else outside of on appinit?

Brad - I am still trying to get you more debugging info, but the framework debug will not come up.  

Chris Hough

On Feb 7, 2012, at 7:47 PM, Chris Hough wrote:

it just shows standard cf debug:

<Screen Shot 2012-02-07 at 7.45.22 PM.png><Screen Shot 2012-02-07 at 7.46.00 PM.png>

br...@bradwood.com

unread,
Feb 8, 2012, 10:16:48 AM2/8/12
to col...@googlegroups.com
Not just the standard debug.  There's a dumped struct in there too-- the one you dumped.

Did you expand the "instance" struct inside of variables to see what was in there? (namely your injected item)

Does the cache debug window show up when you are not aborting yourself?  I didn't mean for you to try and see the cache window AND dump and abort after the error at the same time.

You seemed to indicate that the debug window shows up when you're not aborting.  Did you look in the list of cache keys for your item to see if it is cached?

Thanks!

~Brad
-------- Original Message --------
Subject: Re: [coldbox:13759] model inject model dependency and ocm
From: Chris Hough <chris...@gmail.com>
Date: Tue, February 07, 2012 6:47 pm
To: col...@googlegroups.com, br...@bradwood.com

just shows standard cf debug:

Chris Hough

unread,
Feb 8, 2012, 10:22:26 AM2/8/12
to col...@googlegroups.com, br...@bradwood.com
If I change the block of code to NOT use the injected OCM instance it works fine.  

Yes, the debug shows up as normal, I figured out the abort was blocking it, and when I reviewed the cache objects (after sentence 1) it showed them as normal.  

would you be possibly interested in connecting over IM? it may be easier if you have a few moments.  

Chris Hough

br...@bradwood.com

unread,
Feb 8, 2012, 10:44:42 AM2/8/12
to col...@googlegroups.com
Sorry, but I've got to get back to an emergency project at work.  I'm not sure what to tell you right now other than to try a different approach.

I never inject objects from the cache into my model.  Instead, I like to just have the model ask the appropriate service for what it needs.  The service abstracts the caching inside of itself like so:

function getThing

if cache.exists('thing')
    return cache.get('thing');
else
    var thing = generateThing();
    cache.set('thing',thing);
    return thing
/if

Of course, you'll want some named locks mixed in there if you're concerned about multiple requests all hitting the else at the same time.

Chris Hough

unread,
Feb 8, 2012, 1:17:21 PM2/8/12
to col...@googlegroups.com, br...@bradwood.com
after adding this block to  onrequeststart, i think it's fixed although I am not 100% sure if this is the preferred way

<cffunction name="onRequestStart" returntype="void" output="false">
<cfargument name="event" required="true">
<cfscript>
var rc = event.getCollection();
if(not getColdboxOCM().lookup("DataCompany")){
getColdBoxOCM().set('DataCompany',getModel('Company').DataCompany(),0);
}
if(not getColdboxOCM().lookup("DataMall")){
getColdBoxOCM().set('DataMall',getModel('Mall').DataMall(),0);
}
if(not getColdboxOCM().lookup("DataStates")){
getColdBoxOCM().set('DataStates',getModel('Information').DataStates(),0);
}
if(not getColdboxOCM().lookup("DataUserLevels")){
getColdBoxOCM().set('DataUserLevels',getModel('Permissions').DataUserLevels(),0);
}
if(not getColdboxOCM().lookup("DataNav")){
getColdBoxOCM().set('DataNav',getModel('Menu').DataNav(),0);
}
</cfscript>
</cffunction>

thanks for your help

Chris Hough

br...@bradwood.com

unread,
Feb 8, 2012, 1:27:03 PM2/8/12
to col...@googlegroups.com
That will work I suppose, but I would only do it if every one of those cached objects is used on every request.

I like to abstract my caching as part of my Service (DAO can be acceptable too) so the logic is transparent to the rest of the app and you only incur the hit if you're accessing it.  There's a lot of room for personal preference there, so do what works well for you and is easiest to maintain in your app.
Reply all
Reply to author
Forward
0 new messages