Cache is empty?

3 views
Skip to first unread message

whostheJBoss

unread,
Jun 28, 2009, 8:33:19 PM6/28/09
to transfer-dev
I'm having an issue with the cache and I can't seem to figure out what
the problem is.

I'm using ColdBox / ColdSpring/ Transfer and loading Transfer as a
ColdSpring Bean into the instance scope of one of my handlers from the
ColdBox cache.

So:

<!-- Define Transfer to be used as a bean -->
<bean id="Transfer" factory-bean="ColdboxOCM" factory-method="get">
<constructor-arg name="objectKey"><value>Transfer</value></
constructor-arg>
</bean>

I then call instance.Transfer.get() or save(), etc inside of the
handler and it works fine. It loads a little slowly the first time
while creating the object, but subsequent requests load fast, so I'm
assuming they are cached.

However, if I do this:

rc.cacheTest = instance.Transfer.getCacheMonitor().getCachedClasses();

And then dump the rc.cacheTest variable it always shows up as an empty
array.

instance.Transfer.getCacheMonitor().getTotalCalculatedSize() always
shows up as 0

Why is my Transfer cache not showing anything?

Mark Mandel

unread,
Jun 28, 2009, 8:36:43 PM6/28/09
to transf...@googlegroups.com
Should there be anything in there?

Are you reloading your CB app on every request?

What platform are you on?

Mark
--
E: mark....@gmail.com
T: http://www.twitter.com/neurotic
W: www.compoundtheory.com

whostheJBoss

unread,
Jun 28, 2009, 8:49:41 PM6/28/09
to transfer-dev
I reload the app on the first request to make sure it's fresh, but no
reinits after that.

I have a page that does a view of all of my user objects and a page
that creates them.

The first time I hit the view page it takes a second or two, so I know
it's loading things up. Any hit after that loads almost instantly, so
the objects must already be ready.

I'm on Railo 3.1.0.017 on CentOS 5.3

I know there are some Railo issues, but I've managed to fix most of my
issues I believe.

On Jun 28, 5:36 pm, Mark Mandel <mark.man...@gmail.com> wrote:
> Should there be anything in there?
>
> Are you reloading your CB app on every request?
>
> What platform are you on?
>
> Mark
>
> On Mon, Jun 29, 2009 at 10:33 AM, whostheJBoss
> <dotfus...@changethings.org>wrote:
>
>
>
>
>
> > I'm having an issue with the cache and I can't seem to figure out what
> > the problem is.
>
> > I'm using ColdBox / ColdSpring/ Transfer and loading Transfer as a
> > ColdSpring Bean into the instance scope of one of my handlers from the
> > ColdBox cache.
>
> > So:
>
> > <!-- Define Transfer to be used as a bean -->
> > <bean id="Transfer" factory-bean="ColdboxOCM" factory-method="get">
> >   <constructor-arg name="objectKey"><value>Transfer</value></
> > constructor-arg>
> > </bean>
>
> > I then call instance.Transfer.get() or save(), etc inside of the
> > handler and it works fine. It loads a little slowly the first time
> > while creating the object, but subsequent requests load fast, so I'm
> > assuming they are cached.
>
> > However, if I do this:
>
> > rc.cacheTest = instance.Transfer.getCacheMonitor().getCachedClasses();
>
> > And then dump the rc.cacheTest variable it always shows up as an empty
> > array.
>
> > instance.Transfer.getCacheMonitor().getTotalCalculatedSize() always
> > shows up as 0
>
> > Why is my Transfer cache not showing anything?
>
> --
> E: mark.man...@gmail.com

Mark Mandel

unread,
Jun 28, 2009, 8:56:30 PM6/28/09
to transf...@googlegroups.com
Oh yeah.. what's your cache config?

Mark
--
E: mark....@gmail.com

whostheJBoss

unread,
Jun 29, 2009, 2:35:48 AM6/29/09
to transfer-dev
Ok, a few things. I will explain my configuration first.

I have my Transfer wired up in ColdBox via the Transfer Loader
interceptor:

<!-- Transfer Loader -->
<Interceptor class="coldbox.system.extras.transfer.TransferLoader">
<Property name="ConfigPath">/${AppMapping}/config/transfer.xml.cfm</
Property>
<Property name="definitionPath">/${AppMapping}/config/definitions</
Property>
<Property name="datasourceAlias">MyDataSource</Property>
</Interceptor>

This loads Transfer, TransferTransaction and TransferFactory into the
ColdBox OCM at application startup.

My ColdSpring configuration is set to retrieve Transfer and its
associated beans from the OCM:

<!-- Define Transfer to be used as a bean -->
<bean id="Transfer" factory-bean="ColdboxOCM" factory-method="get">
<constructor-arg name="objectKey"><value>Transfer</value></
constructor-arg>
</bean>
<bean id="TransferTransaction" factory-bean="ColdboxOCM" factory-
method="get">
<constructor-arg name="objectKey"><value>TransferTransaction</
value></constructor-arg>
</bean>
<bean id="TransferFactory" factory-bean="ColdboxOCM" factory-
method="get">
<constructor-arg name="objectKey"><value>TransferFactory</value></
constructor-arg>
</bean>

I have IoC caching off and handler caching disable in my ColdBox
configuration.

When I load up my app for the first time and then visit the view page,
it takes a few seconds (generating objects, etc) and then loads. After
that, any subsequent visits load nearly instantly, so the objects must
already be ready.

For my transfer.xml.cfm I have:

<objectCache>
<defaultcache>
<scope type="instance" />
</defaultcache>
</objectCache>

That is the only reference to caching. Since transfer is loaded into
the OCM by the Transfer Loader interceptor, that is the instance where
the objects should be cached, right?

So...

1.) I check the ColdBox cache for hits and I see that the IoC gets
hits when I refresh my view page but the ColdBox OCM cache for
Transfer stays at 2. Every time I refresh the view page, the IoC in
the ColdBox cache goes up. So, I was wondering how this works. If
Transfer is loaded into the ColdBox cache as Transfer, it shows 2 hits
and never changes, but everytime I call instance.Transfer.get() from
one of my handlers (instance.Transfer is injected from ColdSpring
which is wired to the OCM) the IoC hits go up but the Transfer hits
stay at 2. So, do I have a copy of Transfer in the IoC or what? Is the
one being injected by ColdSpring the one from the cache but the hits
are just being recorded in the IoC hit counter?

2.) I set a variable rc.cache = getPlugin("ioc").getBean
("TransferFactory").getTransfer().getCacheMonitor().getCachedClasses
();

And the result is always an empty array. When I load my pages after
the first time they are fast, so they must be cached somewhere.

Any ideas?

On Jun 28, 5:56 pm, Mark Mandel <mark.man...@gmail.com> wrote:
> Oh yeah.. what's your cache config?
>
> Mark
>
> On Mon, Jun 29, 2009 at 10:49 AM, whostheJBoss
> <dotfus...@changethings.org>wrote:

Mark Mandel

unread,
Jun 29, 2009, 2:53:26 AM6/29/09
to transf...@googlegroups.com
It * sounds * like Transfer is being loaded on every request... I would put some <cflog> statements in TransferFactory's init() function, and see if that is the case.

Mark
--
E: mark....@gmail.com

whostheJBoss

unread,
Jun 29, 2009, 3:11:50 AM6/29/09
to transfer-dev
When you say being loaded, do you mean reloaded? I'll go set up the
logging now, any idea what might be causing this?

On Jun 28, 11:53 pm, Mark Mandel <mark.man...@gmail.com> wrote:
> It * sounds * like Transfer is being loaded on every request... I would put
> some <cflog> statements in TransferFactory's init() function, and see if
> that is the case.
>
> Mark
>

whostheJBoss

unread,
Jun 29, 2009, 5:28:16 AM6/29/09
to transfer-dev
It's weird that the IoC hits to the cache keep going up.

On Jun 28, 11:53 pm, Mark Mandel <mark.man...@gmail.com> wrote:
> It * sounds * like Transfer is being loaded on every request... I would put
> some <cflog> statements in TransferFactory's init() function, and see if
> that is the case.
>
> Mark
>

whostheJBoss

unread,
Jun 30, 2009, 5:30:11 AM6/30/09
to transfer-dev
I thought I'd share what I've done to accomplish what I needed. I have
solved the problem a couple of different ways.

1.) Interceptor for Transfer transactions

Since Transfer's AOP was giving me nightmares, I wrote a quick
interceptor with this method:

<cffunction name="adviseAction" access="public">
<cfargument name="Event" required="true"
type="coldbox.system.beans.requestContext" hint="The event object.">
<cfargument name="interceptData" required="true" type="struct" hint="A
structure containing intercepted information. NONE BY DEFAULT HERE">

<cfscript>
transaction = getPlugin("ioc").getBean("TransferTransaction");
</cfscript>

<cfset transaction.execute(interceptData.component,
interceptData.action, arguments)>

<!--- continue interceptin chain --->
<cfreturn false>

</cffunction>


Then in my preHandler() function for the handler who's actions I want
to be able to advise I added this switch:

switch(Event.getCurrentAction())
{

case "adviseTransaction":
{

data = structnew();
data.action = Event.getValue("originalAction");
data.component = this;
announceInterception('adviseAction', data)
break;
}
}


I then added a route for my handler:

<cfset addCourse(pattern="user/:originalAction",
handler="user",
action="adviseTransaction")>


Finally, for the user.adviseTransaction action that the course matches
to I created an empty method that doesn't do anything but is there to
allow the preHandler to run (which executes the original action on the
handler inside of a transaction):

<cffunction name="adviseTransaction" access="public"
returntype="void" output="false">
<cfargument name="Event" type="coldbox.system.beans.requestContext">
<cfset var rc = event.getCollection()>
</cffunction>


So basically what happens here is this:

When the user.create event is called it is routed to
user.adviseTransaction with a variable available called
"originalAction" which contains the real action that we want to
execute inside of a transaction. In this case, "create".

When user.adviseTransaction runs, the preHandler first matches to the
case and announces an interception to the adviseAction() method of the
interceptor, passing in a structure containing the original action as
data.action and the user handler reference as data.component

The interceptor then retrieves the transaction manager for Transfer
and executes the original method ("create") by using the
interceptData.action variable to identify the action and the
data.component varible to reference the handler. The views, etc are
set inside of the create method since it has access to the Event, the
adviseTransaction method on the handler doesn't need to do anything.

This executes the create method on the user component inside of a
transaction without having to user runEvent(). The Event argument to
the interceptor's adviseAction() method is passed through to
user.create during the execute call.

This effectively wraps an entire handler method inside of a
transaction, so that in case you want to call multiple service layers
and have all of them wrapped under one transaction, you are free to do
so by wrapping the entire handler action.

One thing to remember is that when I have a route such as:

<cfset addCourse(pattern="user/:originalAction",
handler="user",
action="adviseTransaction",
packageResolverExempt="false")>

This sends user.[anything] to user.adviseTransaction, obviously I
don't want this. My user.viewUser has no need to be inside of a
transaction.

So I can do this:

<cfset addCourse(pattern="user/create",
handler="user",
action="adviseTransaction",
packageResolverExempt="false",
matchVariables="originalAction=create")>

This will send only the user/create event to the adviseTransaction()
method.



On alternative way of doing all of this is to avoid the interceptor
entirely and put the method inside of the user handler, like so:

<cffunction name="adviseAction" access="public" returntype="void"
output="false">
<cfargument name="Event" type="coldbox.system.beans.requestContext">
<cfset var rc = event.getCollection()>

<cfscript>
transaction = getPlugin("ioc").getBean("TransferTransaction");
</cfscript>

<cfset transaction.execute(this, rc.originalAction, arguments)>

</cffunction>

And then tell the route to do:

<cfset addCourse(pattern="user/create",
handler="user",
action="adviseAction",
packageResolverExempt="false",
matchVariables="originalAction=create")>

With this configuration, you don't need anything in the preHandler()
method or have an interceptor. The route will pass user/create to
user.adviseAction, which in turn executes the originalAction from the
request collection on "this" (the current handler) inside of a
transaction.

I prefer the handler because it is more flexible, but either way, it
works :)

I can use AOP for singletons, such as service calls and I can wrap my
entire handler action in a transaction using this method.

This has eliminated my stack overflow issues.

On Jun 28, 11:53 pm, Mark Mandel <mark.man...@gmail.com> wrote:
> It * sounds * like Transfer is being loaded on every request... I would put
> some <cflog> statements in TransferFactory's init() function, and see if
> that is the case.
>
> Mark
>
Reply all
Reply to author
Forward
0 new messages