AOP - Intercepting Calls to Methods (when called from w/in the target component)

9 views
Skip to first unread message

penny

unread,
Jul 28, 2008, 3:32:09 PM7/28/08
to ColdSpring-Users
I'm trying to find a way to do this -

Problem: I have a component that has a Step process i.e. Step1, Step2
etc.

Say Step2 is called from Step1 w/in my main Target Method that
ColdSpring and AOP are managing.

But I want to be able to do a 'beforeAdvice' when Step2 is called.

My advisors mappednames properties would be:

<property name="mappedNames">
<value>Step2</value>
</property>

However, when Step1 is called and when done calls <cfset Step2() />,
the BeforeAdvice is never executed.

Is this normal behavior?

When I specify the BeforeAdvice to be 'Step1' it works fine - but not
when the mappedNames named method is called from w/in the component
already. Limitation of AOP or my implementation?

(btw - from my last posts, instead of using the arguments[x] notation
that was preventing my AOP coldspring install to work propertly in all
cases, I decided to explicitly provide cfarguments which works fine)

Kevin Penny
Jobs2Web, Inc.

Barney Boisvert

unread,
Jul 28, 2008, 3:41:12 PM7/28/08
to coldspri...@googlegroups.com
Yes, this is normal behaviour, and no, there is no way to work around
it. ColdSpring AOP is based on proxies, and proxies only exist at the
object instance level, not the method level, so you can only intercept
invocations that enter/exit an instance. Within an instance, any
method calls are opaque to the proxy. Spring AOP (which ColdSpring is
based on) has the same limitation; it's just a side effect of the
proxy-based nature.

With a more comprehensive AOP framework (AspectJ is an example for
Java), you actually use a special compiler that does the weaving at
compile time, allowing you to intercept pretty much anything (even
setting an instance variable!). However, since we don't have access
to the compiler in the CFML runtime, there's no way to do that for
CFCs.

It's also theoretically possible to use a special classloader to that
does the weaving at load time. This approach would be technically
feasible with CFCs, I think, though I don't know of any examples, or
even proof-of-concepts. The basic idea would be that instead of using
createObject(), you'd call your special loader, and it would call
createObject, and then replace all the methods of the instance with
woven methods before returning it to the calling code. The crucial
difference is that it's still returning a single instance, not a
proxied one, so internal method calls will run through the AOP
framework. Could be a fun project...

cheers,
barneyb

--
Barney Boisvert
bboi...@gmail.com
http://www.barneyb.com/

penny

unread,
Jul 28, 2008, 5:12:01 PM7/28/08
to ColdSpring-Users
Thanks for the prompt response - I guess expecting AOP Framework to be
omnipotent was a little too much to excpect ;)

Excellent Stuff - Thanks a bunch

Kevin
> bboisv...@gmail.comhttp://www.barneyb.com/

Dave Ross

unread,
Jul 29, 2008, 7:48:41 AM7/29/08
to coldspri...@googlegroups.com
since coldspring is doing the createObject, it could probably get all sassy and do some runtime method replacement. I think this is just one of those things where the proxy approach works for 99% of use-cases - and there would be a significant engineering effort in doing runtime (load time) weaving.

-Dave

Bryan Hogan

unread,
Jul 29, 2008, 11:58:03 AM7/29/08
to coldspri...@googlegroups.com

I’m looking for a discussion on loading a large number of beans in ColdSpring and in general.   Say you have use ColdSpring’s bean config or another Spring based config and load 100+ components, have 100+ remote proxies, etc.  How would you design for this?

 

Currently I am stuffing every component into the application scope making them available to my developers/designers.  I do not want them of course to manage remote proxies, components, etc.  Everything works well right now at ~30 components.  Now I am looking for ideas to scale so that I can continue to abstract object creation from the developers.

 

It would be great to be able to load these into a better caching framework than the application scope.  Your thoughts?

Jared Rypka-Hauer

unread,
Jul 29, 2008, 12:11:47 PM7/29/08
to coldspri...@googlegroups.com
I'm curious about a couple things:

1) What's wrong with having roughly 100 objects in the application scope? Have you checked to see how much memory that uses? Just FYI - I've been on projects that had that many objects in the application scope and with proper server config it's not a big deal... objects aren't terribly heavy.

2) I'm not sure what alternatives you'd like to discuss other than the application scope, which is where singletons live, unless you want to put them in the server scope, or the session scope. What other boxes to you think we might have available into which to stuff things? While I hesitate to invoke a Java example on this list (because there are hardcore Java guys here and my experience is very limited!), bs I understand it, J2EE apps (and JSP in particular) use the same concept... singletons go in the one scope available for an application: the application scope.

Where else would you put stuff?

J

Bryan Hogan

unread,
Jul 29, 2008, 12:31:41 PM7/29/08
to coldspri...@googlegroups.com

I don’t see anything wrong with putting many objects into the application scope at all.  Right now it takes less than a second to initialize.  I haven’t had a chance yet to get metrics on them.   I am rapidly heading down the path to creating a very large number of objects, remote services, etc because I am taking our app towards a SaS application.

 

What I would like to do is somehow initialize and replicate these objects across a cluster of many servers and then each application loads these objects from the shared space into the application scope.  Feel free to shared Java examples.  Listed below is an example of my current setup.

 

Each Module on each server has its own application name so when it is initialized it loads the component package.  The component package is not unique so there is no need to have a copy on each server.  If for any reason the application reloads for any module I would like to not have to recreate the component package.

 

Server 1

            App 1

                        Module 1

                        Module 2

                        Module 3

                        Module 4

            App 2

                        Module 1

                        Module 2

                        Module 3

                        Module 4

            100+ more (Same setup)

 

            Components Packages

                       

Server 2

            App 1

                        Module 1

                        Module 2

                        Module 3

                        Module 4

            App 2

                        Module 1

                        Module 2

                        Module 3

                        Module 4

            100+ more (Same setup)

 

            Components Packages

 

5 more (Same setup)

 

 


Barney Boisvert

unread,
Jul 29, 2008, 1:36:05 PM7/29/08
to coldspri...@googlegroups.com
At the company I work for, almost all of our applications have a bean
count at least that large. The memory footprint is negligible, though
application startup time is a bit slow to build all those proxies.
But with redundant servers, you can spend that startup while the
server is offline, and just roll across the cluster to get everything
updated.

In short, 100 beans is no big deal. Worry about performance later
when you have a measurable problem. I suspect that it's still a LONG
ways away.

cheers,
barneyb

--

Bryan Hogan

unread,
Jul 29, 2008, 1:56:10 PM7/29/08
to coldspri...@googlegroups.com
The planned release for this is early November. The framework and
components are ready to go for the most part. I can define them in the
config and we're off and running. This is a high priority for me right
now. I can easily see this become near 1000 objects including remote
proxies.

Worrying about performance when it becomes a problem is what I am trying
to avoid.

If it were just one app loading the factory than I wouldn't be so
concerned, however, there are ~100 apps with 5 modules each. Each time
one of the servers in the cluster fails I want to avoid having to
recreate the factory. If one server fails than there are 500
re-initializations of the factory. No it's not a huge deal, but if I
can avoid reloading the objects than that would be great.

For caching I'm starting to implement memcache. I've considered
stuffing the objects in there; however, because of the array limitation
for serialization of the object I don't see a way.

I've considered creating a command line C# application that iterates
through the config files and loads the apps before a user can hit it.
May be an option but doesn't seem elegant to me.

There has to be some way to be able to share initialized objects across
apps.

-----Original Message-----
From: coldspri...@googlegroups.com
[mailto:coldspri...@googlegroups.com] On Behalf Of Barney Boisvert
Sent: Tuesday, July 29, 2008 10:36 AM
To: coldspri...@googlegroups.com
Subject: [coldspring-users] Re: Loading large numbers of beans.


Barney Boisvert

unread,
Jul 29, 2008, 2:05:30 PM7/29/08
to coldspri...@googlegroups.com
> There has to be some way to be able to share initialized objects across
> apps.

An object instance can only exist in one JVM's memory space at any one
time. If you send it to memcached, or whatever, you're duplicating it
and sending a copy, so I'm not sure what you're trying to achieve.

Similarly, if you server crashes, the JVM is gone and has to be
repopulated with the necessary objects. Whether you're using
ColdSpring to call createObject for you or inflating them off a
serialized storage in memcached, you still have to create all those
objects in the JVM's memory after the server starts back up.

For the two main apps that I work on all day, initializing a new copy
of the app usually takes around 3.5 minutes. But with clustering,
it's irrelevant, as long as you ensure the server isn't added back
into the cluster until it's initialized, including prebuilding any
caches that it might need.

cheers,
barneyb

On Tue, Jul 29, 2008 at 10:56 AM, Bryan Hogan <bho...@edonor.com> wrote:
>
> The planned release for this is early November. The framework and
> components are ready to go for the most part. I can define them in the
> config and we're off and running. This is a high priority for me right
> now. I can easily see this become near 1000 objects including remote
> proxies.
>
> Worrying about performance when it becomes a problem is what I am trying
> to avoid.
>
> If it were just one app loading the factory than I wouldn't be so
> concerned, however, there are ~100 apps with 5 modules each. Each time
> one of the servers in the cluster fails I want to avoid having to
> recreate the factory. If one server fails than there are 500
> re-initializations of the factory. No it's not a huge deal, but if I
> can avoid reloading the objects than that would be great.
>
> For caching I'm starting to implement memcache. I've considered
> stuffing the objects in there; however, because of the array limitation
> for serialization of the object I don't see a way.
>
> I've considered creating a command line C# application that iterates
> through the config files and loads the apps before a user can hit it.
> May be an option but doesn't seem elegant to me.
>
>

Bryan Hogan

unread,
Jul 29, 2008, 2:31:32 PM7/29/08
to coldspri...@googlegroups.com
I understand that the objects do have to be recreated into memory. I
guess what I'm concerned about is the time it takes to get them into
memory.

Is it possible in any way to create an object and save it into memory
and have that memory be persistent so it will never have to be recreated
by each individual app?

Let's say it took 4 minutes to load the objects for each application and
you have 500 unique application names. This would take a good deal of
time to re-initialize all of the objects on a server.

To mitigate this problem the objects could be saved into the server
scope. So then it should only take 4 minutes to load the objects for
each server.

A downtime of four minutes is ok for a single server as long as the rest
are running. However, it would be nice if there were a way to instead
of having an instance of the objects in the server scope for each server
that they all shared the same instance. This is what made me think of
using memcache. I thought possibly it would be quicker to deserialize
the objects from memcache than to re-initialize them with
createObject().

Barney Boisvert

unread,
Jul 29, 2008, 2:45:47 PM7/29/08
to coldspri...@googlegroups.com
On Tue, Jul 29, 2008 at 11:31 AM, Bryan Hogan <bho...@edonor.com> wrote:
> To mitigate this problem the objects could be saved into the server
> scope. So then it should only take 4 minutes to load the objects for
> each server.

Yeah, that'd work, as long as none of the object stored any
application-specific state. Or I suppose you could design your
objects to have buckets for per-application state inside, so they take
care of it internally.

> A downtime of four minutes is ok for a single server as long as the rest
> are running. However, it would be nice if there were a way to instead
> of having an instance of the objects in the server scope for each server
> that they all shared the same instance. This is what made me think of
> using memcache. I thought possibly it would be quicker to deserialize
> the objects from memcache than to re-initialize them with
> createObject().

I don't know that doing that would avoid the CFC instantiation
overhead, because I'd wager that the serialized form of a CFC is a CFC
name plus the instance's state, and deserialization is createObject()
on that CFC name and then state injection. You can't do "normal"
deserialization with a Java class name, because the Java class that
represents a CFC isn't stable (at least on ColdFusion). That's a
question for the Adobe engineers, though you could probably do some
performance profiling and figure it out.

cheers,
barneyb

Bryan Hogan

unread,
Jul 29, 2008, 2:53:02 PM7/29/08
to coldspri...@googlegroups.com
Thanks for your feedback Barney. I wish there were a way that we could
see to avoid the churn object creation makes.

-----Original Message-----
From: coldspri...@googlegroups.com
[mailto:coldspri...@googlegroups.com] On Behalf Of Barney Boisvert
Sent: Tuesday, July 29, 2008 11:46 AM
To: coldspri...@googlegroups.com
Subject: [coldspring-users] Re: Loading large numbers of beans.

Dave Ross

unread,
Jul 29, 2008, 4:56:34 PM7/29/08
to coldspri...@googlegroups.com
The only way is to not create so many objects at start up.

Basically, everything I've read in this thread smells like "refactor" to me.

Bryan Hogan

unread,
Jul 29, 2008, 4:57:17 PM7/29/08
to coldspri...@googlegroups.com

Why do you suggest refactoring?

 


From: coldspri...@googlegroups.com [mailto:coldspri...@googlegroups.com] On Behalf Of Dave Ross
Sent: Tuesday, July 29, 2008 1:57 PM
To: coldspri...@googlegroups.com
Subject: [coldspring-users] Re: Loading large numbers of beans.

 

The only way is to not create so many objects at start up.

Dave Ross

unread,
Jul 29, 2008, 5:12:14 PM7/29/08
to coldspri...@googlegroups.com
If the apps are using the same code (which they are, since you said server scope is an option) - why are they *different* apps?

Peter J. Farrell

unread,
Jul 29, 2008, 5:19:38 PM7/29/08
to coldspri...@googlegroups.com
Bryan Hogan said the following on 7/29/2008 1:53 PM:

> Thanks for your feedback Barney. I wish there were a way that we could
> see to avoid the churn object creation makes.
>

Bryan, have you profiled what is taking so long for your application to
startup? It's easy to point at object creation as the problem, but a
lot of other stuff can occur between the start and end of object
creation including populating in data from a database. I have an
application with rather large model (300+ model objects) and it takes
our production servers about 30-45 seconds to load. I am very aware
that the major addition loading time can come from loading information
from the database into the object during the creation of the object.
We've been careful not to do that unless necessary. You could easily
have an other application take care of loading of queries / data into a
MemCached cluster and have all your applications use that data instead.

.pjf

Bryan Hogan

unread,
Jul 29, 2008, 5:20:14 PM7/29/08
to coldspri...@googlegroups.com

The application is an app that is almost 10 years old.  I have been refactoring it for going on 2 years.  Most of the main logic has been separated into components.  Because of this I am opening it up as SaS for vendors, etc.

 

There is still a lot of functionality that is procedural that is being extracted into the shared components.  I understand your concern because this is what I have been working on separating for a long time.  Eventually there will be only one code base.  The components are this library.  When code is refactored it is placed into the component library and provided as services via remote proxies and to the developers working in the “view”.

 

I thought you meant I should refactor the library because there are so many objects.

Bryan Hogan

unread,
Jul 29, 2008, 5:53:17 PM7/29/08
to coldspri...@googlegroups.com
" Bryan, have you profiled what is taking so long for your application
to
startup? "

I have profiled it and it runs fantastic. I'm planning for the worst
case scenario.

Fortunately I only have one load from the DB on start up.

-----Original Message-----
From: coldspri...@googlegroups.com
[mailto:coldspri...@googlegroups.com] On Behalf Of Peter J. Farrell
Sent: Tuesday, July 29, 2008 2:20 PM
To: coldspri...@googlegroups.com
Subject: [coldspring-users] Re: Loading large numbers of beans.


Brian Kotek

unread,
Jul 29, 2008, 6:58:07 PM7/29/08
to coldspri...@googlegroups.com
If the number of objects and the number of apps is that large, and you're running it on a cluster, it should be fairly easy to load up the beans before you return the server to the cluster.

Otherwise, what you're asking for isn't possible at this time as far as I know. You can't share CFC instances across servers. Even Railo's upcoming cluster scope doesn't actually share instances, but duplicates them (to the best of my knowledge). So the "overhead" of building things up remains. As far as remote proxies, they are standalone CFCs and aren't actually kept in any scope, so there is no replication of those.

In reality the apps should only need to be reinitialized rarely anyway so it's not like this is going to happen all the time.

Mark Mandel

unread,
Jul 29, 2008, 9:38:53 PM7/29/08
to coldspri...@googlegroups.com
That's how Transfer does it's AOP implementation for its Transaction services.

It generates proxy methods, and then moves around the methods in the
variables scope that it is proxying, so it ends up being in a
different place.

Currently it only does 1 level deep AOP, do you can't AOP over AOP
like you can with ColdSpring, but I haven't had the need to solve it
yet, as there is only Transaction advice with Transfer.

Mark

--
E: mark....@gmail.com
W: www.compoundtheory.com

Reply all
Reply to author
Forward
0 new messages