[wirebox 1.1.1] - Singleton question

56 views
Skip to first unread message

brett

unread,
Jun 1, 2012, 1:48:49 PM6/1/12
to ColdBox Platform
Now that I'm able to see the debug information coming from wirebox,
I'm noticing that there seems to be an awful lot of instances being
rebuilt even though I have (or think I have) them marked as singletons
in my wirebox config. This is really slowing down my development.

I have two directories under my model directory in my cbox app:

1) repositories
2) services

The repositories really just act like a data gateway for accessing my
database; and my services directory contains services for security,
biz logic, etc. that make use of the repositories via some cfproperty
injection. My intent with these services and repositories is that
they are put into the singleton scope so they are just there all wired
up for whatever I need them for. My wirebox config looks like this:

// Map Bindings below
map('appdsn').toValue(getProperty('datasources').appdsn.name);
mapDirectory('/model.repositories').asSingleton();
mapDirectory('/model.services').asSingleton();

What I'm seeing in my logbox files (see below) is that each time the
LookupRepository is referenced by another service or anything else, it
looks like its being completely rebuilt by wirebox when I would expect
it to just pull it out of the singleton scope and pass it to whoever's
calling it. As an example the log sample below repeated 12 times
during the processing of one specific event when I would have only
expected to see it once. Does that seem right?

Thanks in advance.
Brett



LOGOX DEBUGGING

"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Instance
object built: LookupRepository:/model.repositories.LookupRepository"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Instance
object built: appdsn:"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Dependency:
{JAVACAST={null},NAME={appdsn},DSL={model},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}}
--> injected into LookupRepository"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Dependency:
{JAVACAST={null},NAME={DataManipulationPlugin},DSL={coldbox:myPlugin:DataManipulation},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}}
--> injected into LookupRepository"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Dependency:
{JAVACAST={null},NAME={logger},DSL={logbox:logger},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}}
--> injected into LookupRepository"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Finalized
Autowire for: LookupRepository ExtraInfo:
{DICONSTRUCTORARGS={[]},DIPROPERTIES={[{JAVACAST={null},NAME={appdsn},DSL={model},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}},
{JAVACAST={null},NAME={DataManipulationPlugin},DSL={coldbox:myPlugin:DataManipulation},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}},
{JAVACAST={null},NAME={logger},DSL={logbox:logger},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}}]},PROVIDERMETHODS={[]},NAME={LookupRepository},DSL={},DISCOVERED={true},SCOPE={NoScope},AUTOASPECTBINDING={true},PATH={/
model.repositories.LookupRepository},AUTOINIT={true},EAGERINIT={false},DISETTERS={[]},ALIAS={[LookupRepository]},ONDICOMPLETE={[]},VALUE={},METADATA={{NAME={model.repositories.LookupRepository},FULLNAME={model.repositories.LookupRepository},PROPERTIES={[Ljava.lang.Object;@620205f2},PATH={C:
\ColdFusion9\wwwroot\MyApp\model\repositories
\LookupRepository.cfc},EXTENDS={{NAME={model.repositories._BaseRepository},FULLNAME={model.repositories._BaseRepository},PROPERTIES={[Ljava.lang.Object;@23fcc817},FUNCTIONS={[Ljava.lang.Object;@28b47076},PATH={C:
\ColdFusion9\wwwroot\MyApp\model\repositories
\_BaseRepository.cfc},EXTENDS={{PATH={C:\ColdFusion9\wwwroot\WEB-INF
\cftags\component.cfc},NAME={WEB-INF.cftags.component},FULLNAME={WEB-
INF.cftags.component},TYPE={component}}},TYPE={component}}},OUTPUT={no},TYPE={component}}},AUTOWIRE={true},CACHE={{KEY={},PROVIDER={default},LASTACCESSTIMEOUT={},TIMEOUT={}}},DIMETHODARGS={[]},METHOD={},CONSTRUCTOR={init},ASPECT={false},TYPE={cfc}}"
"DEBUG","COLDBOXFILE","06/01/2012","13:20:56","coldbox.system.ioc.Injector","Dependency:
{JAVACAST={null},NAME={LookupRepository},DSL={id:LookupRepository},REQUIRED={false},SCOPE={variables},VALUE={null},REF={null}}
--> injected into MyService"



br...@bradwood.com

unread,
Jun 5, 2012, 6:15:01 PM6/5/12
to col...@googlegroups.com
Since the Binder config is programmatic, you could use a loop construct based on a directory listing of the contents of that folder and then dynamically do map("foo").to("bar").initArg() bit on each one.  I've never done it and I'm not sure if it's recommended, but it would work.

As far as the DI annotations not being inherited, I just so happen have a pull request for that committed to my ColdBox fork on Github that is currently waiting on Luis to review.  That would allow you to put the annotations once in the base object.  Maybe if Luis looks at my enhancement soon and it passes review, it will make it into 3.5.2.  :)

Thanks!

~Brad
-------- Original Message --------
Subject: [coldbox:15097] Re: - Singleton question
From: Cristian Pop <cri...@gmail.com>
Date: Tue, June 05, 2012 11:45 am
To: col...@googlegroups.com

Hi,

Sorry for the highjacking. 

Brad, do you know another solution for recursing chaining for mapDirectory ? I assumed that chaining works with mapDirectory but I discovered after reading your post that is only applied to the last cfc found. I'm trying to migrate some old code to wirebox and I have a lot of CFC in a folder that access DB and requires a DSN so i tried something like :

mapDirectory(packagePath="app.model.db").initArg(name="datasource", value="test");

I don't want to change them all to allow DSN injection and I also noticed that metadata inheritance is not working (they inherit a common db object).

Thanks

On Saturday, June 2, 2012 12:43:46 AM UTC+3, Brad Wood wrote:
Most excellent news!

Thanks!

~Brad

On Friday, June 1, 2012 4:16:17 PM UTC-5, brett wrote:
Brad,

Just updated the CFC's in my services and repositories directory to
include the singleton attribute and it worked beautifully.  Thanks so
much for your help.  My pages are loading at least ten times faster.

Brett


--
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

Brad Wood

unread,
Jun 5, 2012, 3:36:05 PM6/5/12
to col...@googlegroups.com
You know, now that I think about it, my pull request is specifically for component-level annotations to inherit but there aren't any component-level annotations for init args. If your base object has an init method with arguments that can be injected, that should already be picked up by WireBox and processed. Of course, if your sub classes override the init method, they'll need to specify the same init args and inject annotations if applicable.

Can you show us the code?

Thanks!

~Brad

Sent from my ASUS Eee Pad

Cristian Pop

unread,
Jun 6, 2012, 6:32:49 AM6/6/12
to col...@googlegroups.com
Sure, I simplified the code... (How the hell do I format code here ? )

The base Object: 

<cfcomponent name="dbObject" displayname="dbObject">
<cfproperty name="datasource" type="string"/>
<cffunction name="init" access="public" returntype="dbObject" output="false" hint="dbObject Constructor.">
       <cfargument name="datasource" type="string" required="true">
  <cfset variables.instance.datasource   =  arguments.datasource />
  <cfreturn this />
</cffunction>

<cffunction name="getDatasource" access="private" returntype="string">
  <cfreturn variables.instance.datasource />
</cffunction>
</cfcomponent>


Sample GTW Object:

<cfcomponent name="MyGTW" displayname="MyGTW" output="false" hint="" extends="dbObject">
<cffunction name="init" access="public" returntype="MyGTW" output="false" displayname="init" hint="constructor">
<cfargument name="datasource" type="string" required="true"/>
<cfset super.init(arguments.datasource) />
<cfreturn this />
</cffunction>
<cffunction name="getAll" access="public" returntype="query" output="false" displayname="getAll" hint="">
<cfset var getQry = ""/>
<cfquery name="getQry" datasource="#getDatasource()#">
                ...
</cfquery>
<cfreturn getQry/>
</cffunction>
</cfcomponent>


And I have a factory object instantiated with the DSN string:


<cfcomponent displayname="dbFactory" output="false">
<cfproperty name="datasource" type="string" default="lhp"/>

<cffunction name="init" access="public" returntype="any">
  <cfargument name="datasource" type="string" required="true">
  <cfset variables.instance.datasource  =  arguments.datasource />
  <cfreturn this />
</cffunction>

<cffunction name="getDatasource" access="private" returntype="string">
  <cfreturn variables.instance.datasource />
</cffunction>


<cffunction name="create" access="public" returntype="any">
  <cfargument name="name" type="string" required="true">
  
          <cfreturn createObject("component","app.model.db.#arguments.name#").init(getDatasource())/>
       </cffunction>

</cfcomponent>

I'm trying to move to wirebox and my initial approach was to mapDirectory('app.model.db').initArg(...) and then replace the create object in the factory with wirebox.getInstance. 

Thanks for your input,

Cristian
To unsubscribe from this group, send email to coldbox-unsubscribe@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
To unsubscribe from this group, send email to coldbox-unsubscribe@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
To unsubscribe from this group, send email to coldbox-unsubscribe@googlegroups.com

Cristian Pop

unread,
Jun 6, 2012, 9:33:39 AM6/6/12
to col...@googlegroups.com
Bratt, don't mind me. I guess I was tired. I can pass the DSN string in the getInstance call in the factory, so no need for chaining  to work on mapDirectory, But you improvement can indeed be useful.

Cristian

Tom Miller

unread,
Jun 6, 2012, 9:55:14 AM6/6/12
to col...@googlegroups.com

Bratt? Sorry, but I lol’d :)

To unsubscribe from this group, send email to coldbox-u...@googlegroups.com

To unsubscribe from this group, send email to coldbox-u...@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

--

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

br...@bradwood.com

unread,
Jun 6, 2012, 11:10:13 AM6/6/12
to col...@googlegroups.com
I don't use init args that often, but what you showed SHOULD work providing you have a WireBox mapping named "datasource".  "inject" defaults to true for init arguments, and the mapping ID defaults to the name of the argument.  Alternatively, it could look like this:

 <cfargument name="datasource" type="string" required="true" inject="coldbox:datasouce:myDSName">

Thanks!

~BRad
To unsubscribe from this group, send email to coldbox-unsubscribe@googlegroups.com
To unsubscribe from this group, send email to coldbox-unsubscribe@googlegroups.com
To unsubscribe from this group, send email to coldbox-unsubscribe@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

br...@bradwood.com

unread,
Jun 6, 2012, 11:17:29 AM6/6/12
to col...@googlegroups.com
Yep, assuming you do something like:

<cffunction name="create" access="public" returntype="any">
  <cfargument name="name" type="string" required="true">
    <cfset local.args = {}>
    <cfset local.args.datasource = getDatasource()>
    <cfreturn wirebox.getInstance(name=arguments.name, initArguments=local.args)>
</cffunction>

Note, it is unnecessary to call the init() yourself now.

As far as formatting code in the list, Google Groups allows for HTMl formatting, but you can't really control where the lines will break.

Thanks!

~Brad
-------- Original Message --------
Subject: Re: [coldbox:15106] Re: - Singleton question
From: Cristian Pop <cri...@gmail.com>
Date: Wed, June 06, 2012 8:33 am
To: col...@googlegroups.com

Bratt, don't mind me. I guess I was tired. I can pass the DSN string in the getInstance call in the factory, so no need for chaining  to work on mapDirectory, But you improvement can indeed be useful.

Cristian

On Wednesday, June 6, 2012 1:32:49 PM UTC+3, Cristian Pop wrote:

br...@bradwood.com

unread,
Jun 6, 2012, 11:18:11 AM6/6/12
to col...@googlegroups.com
Not the worst I've been called.  :)

Reply all
Reply to author
Forward
0 new messages