• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Cloning CFC instances In Memory

New Here ,
Jul 19, 2006 Jul 19, 2006

Copy link to clipboard

Copied

We have a framework which can create hundreds of CFCs per page request. Most of the request time is used when a CreateObject("component", "....") is executed. This time is large because template caching must be disabled for other reasons. When the cache is enabled, the execution time is reduced significantly, sometimes by a factor of 5 or more.

To compensate, I'd like to keep a prototype of each CFC I will be creating in memory, and then clone the one that currently resides in memory to avoid disk I/O. Note that I don't want a "deep copy" of a CFC because they should be empty prototypes anyways.

This is possible in Java using the Object.clone() (deep copy) method or perhaps Object.getClass().newInstance() (empty copy), of which the latter approach is the one I'd like to take.

I've tried writing a simple function in Java to do this:
public static createFromInstance(Object obj) {
...
return obj.getClass().newInstance();
...
}

but trying to use this method within ColdFusion gives undefined variables exceptions.

We are using CF 6.1, but we may consider a move to 7. Perhaps using the CFCProxy class in 7.0.1 will work. Has anyone tried this method or has anyone written a Java or ColdFusion solution using 6.1? Can anyone explain the underlying mechanism of how CFCs map to Java objects, and how it might be possible to clone them?
TOPICS
Advanced techniques

Views

661

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jul 21, 2006 Jul 21, 2006

Copy link to clipboard

Copied

CFC are ColdFusions version of Objects, however they are not instances of a java class so you can't clone them. Sorry.

Can you reuse the same instance, and call a reset function between uses?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 21, 2006 Jul 21, 2006

Copy link to clipboard

Copied

I've considered keeping a pool of CFC to reuse, but I think it will quickly become too messy and complex to be a sustainable approach. We're talking an extremely high volume site.

I thought CF compiles CFCs into Java classes, as it does for .cfm pages.

This is really boils down to the lack of control of template caching, where it would be nice to do something like
<cfsetting enabletrustedcache="true">...</cfsetting>

I've written a similar custom tag, but because template cache is per server (not per request or even per application), that's not going to work in any meaningful way,

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jul 22, 2006 Jul 22, 2006

Copy link to clipboard

Copied

It does compile them into java, but not into a simple java class that could be cloned. It's more like a set of proxy objects.

There is a way to make setting changes like this on a per application basis. The trick is to use the j2ee version. If you install CF with the multi-version version you'll be able to deploy CF has a war for each portion of the application.

For instance right now you have your app broken up into subfolders. However what you can do is make each of those folders a new cf "war" deployment. Which makes each sub folder a standalone application complete with it's own cfadmin.

It's a trickier config then the simple standalone, and it does take a few more resources. But you'll get a lot more control. Of course read the CF docs on .war deployment before you do anything. But once you get used to breaking your apps up this way you'll always do it.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 22, 2006 Jul 22, 2006

Copy link to clipboard

Copied

This requirement has been around for a few years now: basically since 6.1
and people starting to use CFCs with anger.

For CFMX7, the best Macromedia could come up with was causing duplicate()
to error if one tried to duplicate() a CFC instance (cf earlier versions
which "duplicated" them into a struct). Are they actually thinking of
fixing duplicate() so that it does actually duplicate the CFC instance?
This "fix" to duplicate() in CFMX7 was a bit of a slack effort.

--
Adam

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 22, 2006 Jul 22, 2006

Copy link to clipboard

Copied

I wonder whether the pound (#) signs ensure that obj is a copy of comp.

<cfobject component="mycomponent" name="comp" >
<cfobject action="CREATE" type="JAVA" class="java.lang.Object" name="obj">
<cfset obj = #comp#>
<cfinvoke component="#obj#" method="myfunc" <!--- etc. ---> />

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 22, 2006 Jul 22, 2006

Copy link to clipboard

Copied

a quick check:


<cfset obj = CreateObject("java", "java.lang.Object").init() />
<cfdump var="#obj.toString()#" /><br />

<cfset newInstance = #obj# />
<cfdump var="#newInstance.toString()#" />


reveals this is not the case.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 23, 2006 Jul 23, 2006

Copy link to clipboard

Copied

> a quick check:

> <cfset obj = CreateObject("java", "java.lang.Object").init() />
> <cfdump var="#obj.toString()#" /><br />
> <cfset newInstance = #obj# />
> <cfdump var="#newInstance.toString()#" />

> reveals this is not the case.


Not quite. You're not comparing like with like. My suggestion involves two objects, not two instances of the same object.

Below, I have integrated your logic into my suggestion. The pounds (#) may not be necessary. However, I include them to further insist to Coldfusion to pass by value rather than by reference.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jul 23, 2006 Jul 23, 2006

Copy link to clipboard

Copied

> The pounds (#) may not
> be necessary. However, I include them to further insist to Coldfusion to pass
> by value rather than by reference.

It does nothing of the sort. Pound-signs simply flag to CF that a char
sequence represents a variable name rather than a string, in situations
where there could be ambiguity:
- within a string, eg: "My name is #name#", as opposed to "My name is
name".
- outside of CF tags, eg: <cfoutput>My name is #name#</cfoutput>, as
opposed to <cfoutput>My name is name</cfoutput>

Within your example there is no ambiguity, so the pound signs are simply
redundant.

All your sample code is, likewise, redundant.

All you are demonstrating is that the copied-by-reference objects have
different REFERENCES. Well of course they do. Each of those references
(different memory locations in the stack) point to the same memory location
(in the heap) for the actual object instance data.

When you set obj to null, you are setting the REFERENCE to null, not the
object. Incidentally, no GC will be done on the object until ALL the
references to it are deleted (and even then, only when Java decides to do
it).

There is - currently - NO WAY to clone / duplicate an object in CF. If
you want to do so, you need to roll your own method which (recursively)
creates a new object instance and clones/duplicates its variables and this
scopes. That's as good as it gets.

--
Adam

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 23, 2006 Jul 23, 2006

Copy link to clipboard

Copied

LATEST
> The pounds (#) may not
> be necessary. However, I include them to further insist to Coldfusion to pass
> by value rather than by reference.

It does nothing of the sort. Pound-signs simply flag to CF that a char
sequence represents a variable name rather than a string, in situations
where there could be ambiguity:
- within a string, eg: "My name is #name#", as opposed to "My name is
name".
- outside of CF tags, eg: <cfoutput>My name is #name#</cfoutput>, as
opposed to <cfoutput>My name is name</cfoutput>

Within your example there is no ambiguity, so the pound signs are simply
redundant.

All your sample code is, likewise, redundant.


I'll simply repeat the Coldfusion fact. The statement <cfset var1 = #var2#> assigns the value of var 2 to the variable var1.

All you are demonstrating is that the copied-by-reference objects have
different REFERENCES. Well of course they do. Each of those references
(different memory locations in the stack) point to the same memory location
(in the heap) for the actual object instance data.


No disagreement there, as my code in fact demonstrates the point. It was simply to show Coffeeflower that my starting point was two objects rather than two instances of one object.

When you set obj to null, you are setting the REFERENCE to null, not the
object. Incidentally, no GC will be done on the object until ALL the
references to it are deleted (and even then, only when Java decides to do it).


Your argument is still good in Java. However, I think it needs some qualification in Coldfusion. My hypothesis is based on the pound (#) symbol, for which there is no equivalent in Java. I'll maintain the distinction you make between references on the stack and objects on the heap. Not only is it unimpeachable, it will now help me present my hypothesis more clearly.

An object reference points to the location of an object and its metadata on the heap. Object references, like the primitives,

<cfset myVar = 5>
<cfset x = #myVar#>

are stored on stack memory. I therefore wonder whether one can use the pound (#) symbol, or any other native Coldfusion technique, to create a primitive-like assignment. Could we, by replacing the reference to the heap with a primitive value assignment, create a copy of an object on the stack?


Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation