Creating Multiple Instances From The Same Java Class In ColdFusion

Posted May 25, 2007 at 2:54 PM by Ben Nadel

Tags: ColdFusion

The other day, I came across a cool little feature of ColdFusion that I was not aware of. Usually, when I go to create a Java object, I use the ColdFusion CreateObject() method and give it the Java class name that I want to create. I don't fully understand that magic that is CreateObject() and so, I assumed that you needed to call it for every single Java object that you wanted to create.

As it turns out, though, you only need to create the Java class once and then you can call the constructor method, Init(), on it as many times as you want. Check out this simple demo that utilizes one java.lang.StringBuffer class to create two StringBuffer instances:

  • <!---
  • Create a class of the Java string buffer.
  • From this class, we are then going to instantiate
  • new StringBuffer instances.
  • --->
  • <cfset objStringBuffer = CreateObject(
  • "java",
  • "java.lang.StringBuffer"
  • ) />
  •  
  •  
  • <!---
  • Create two string buffer objects by calling
  • the constructor on the ONE StringBuffer class.
  • --->
  • <cfset objBufferA = objStringBuffer.Init() />
  • <cfset objBufferB = objStringBuffer.Init() />
  •  
  •  
  • <!--- Add some text to string buffer A. --->
  • <cfset objBufferA.Append(
  • "Put it in my A!"
  • ) />
  •  
  • <!--- Add some text to string buffer B. --->
  • <cfset objBufferB.Append(
  • "Put it in my B!"
  • ) />
  •  
  •  
  • <!---
  • Output the two different string buffers. I do not
  • expect them to be different, but I have never called
  • Init() twice on the same object, so I am not sure
  • how it will work.
  • --->
  • <p>
  • BufferA: #objBufferA.ToString()#<br />
  • BufferB: #objBufferB.ToString()#
  • </p>

Running the above code, we get:

BufferA: Put it in my A!
BufferB: Put it in my B!

Each Init() call created a new StringBuffer instance that received it's own Append() data. How freakin' cool is that? I am sure those of you who are more Java-savvy are looking at that and thinking, "Well yeah - how else did you expect it work?" Yeah, well I don't know that stuff :) I guess the CreateObject() returns a class definition and then the Init() method is reflectively calling the "new" constructor on that class definition or something? It's all voodoo to me.




Reader Comments

May 26, 2007 at 10:00 AM // reply »
79 Comments

Well, yeah I might have asked "how did you expect it to work," =) except that I see the issue where I think confusion can arise. I would have thought (if I had not ever done it) that create object created the object and returned it, and thus you would be calling the constructor of an already constructed object, since thats how we do it in CF.

Its too bad they didn't just make constructors a default part of the language. I see why it might be difficult to do now (although, I think someone who thought about it long enough might find a way to do it that won't break anything). Then, we wouldn't have a disconnect between the way it works for Java and the way it works for CF.


May 26, 2007 at 10:07 AM // reply »
11,238 Comments

@Sam,

Can you give me the 2 second run down on what CreateObject() is actually returning? I assume is has something to do with the difference between a class and an instance of that class??

Like, when I think about Java (and I haven't coded it in years, so this might be incorrect), I think:

String foo = new String( "bar" );

To me that is one statement, so it was not obvious to me that object instantiation through ColdFusion would be in two parts - CreateObject() and then Init().


May 26, 2007 at 10:22 AM // reply »
79 Comments

I had never thought to look until you just asked. So, I looked and I'm getting funny things happening.

If I do this (notice no initialization of sb):

<cfset sb = CreateObject("java","java.lang.StringBuffer")/>
<cfset sb2 = sb.init()>
<cfset sb.append("hello")>
<cfset sb2.append("wassup?")>

<cfoutput>
#sb.ToString()#<br/>
#sb2.ToString()#
</cfoutput>

Both sb and sb2 are the same object.

But if I do this (addition of sb3):
<cfset sb = CreateObject("java","java.lang.StringBuffer")/>
<cfset sb2 = sb.init()>
<cfset sb3 = sb.init()>
<cfset sb3.append("hello")>
<cfset sb2.append("wassup?")>

<cfoutput>
#sb3.ToString()#<br/>
#sb2.ToString()#
</cfoutput>

They are different objects.

And finally, if I do this:

<cfset sb = CreateObject("java","java.lang.StringBuffer")/>
<cfset sb2 = sb.init()>
<cfset sb3 = sb.init()>
<cfset sb3.append("hello")>
<cfset sb2.append("wassup?")>

<cfoutput>
#sb.ToString()#<br/>
#sb2.ToString()#
</cfoutput>

(notice we are outputting sb, NOT sb3) they are different objects with sb == sb3 != sb2.

So in short, I'm clueless as to what's actually going on. But I would have guessed at something like createobject was returning an object of type Class which represented StringBuffer (not sure if I'm saying that correctly or not, but I think you get the idea)


May 26, 2007 at 10:26 AM // reply »
79 Comments

Oh, and I should have said (in the last bit) that clearly, that doesn't appear to be the case (createObject returning an object of type Class that represented StringBuffer).


May 26, 2007 at 10:44 AM // reply »
25 Comments

Hi Ben,
CreateObject for a java class, simply creates a proxy for the class. Thus at this point, only the class gets loaded. Its only when you call a constructor explicitly using 'init' or when you call a non-static method, the class gets intantiated.
Probably the reasons it is like this are

1. If all you need to call is a static method, why to instantiate the object unnecessarily. Object instantiation is costly.
2. We wanted to keep the syntax clean. For createObject to return the actual object, it would require all the constructor arguments here itself, which will complicate the syntax.

Rupesh


May 26, 2007 at 10:52 AM // reply »
79 Comments

Rupesh, that makes sense. Is that documented somewhere?


May 26, 2007 at 1:31 PM // reply »
11,238 Comments

@Sam,

Thanks for doing a little digging.

@Rupesh,

That sounds pretty good. I need to study up on my Java to really fully contact with what it is you are saying. I just need to wrap my head around what a Class is vs. what an object is. Thanks!


May 26, 2007 at 2:59 PM // reply »
120 Comments

"I guess the CreateObject() returns a class definition and then the Init() method is reflectively calling the "new" constructor on that class definition or something? It's all voodoo to me."

You guessed correctly.

This behavior is what allows you to manipulate the static methods and data in a Java class within ColdFusion.

There's a gotcha to be aware of tho'... once you have your class (definition), if you attempt to reference any non-static method or data before calling init(), ColdFusion will automatically call init() with no arguments for you. That's how you can access some Java objects without explicitly calling init() with no arguments.

I don't know whether it will still allow you to call init() explicitly to create a new instance but it's something to be careful about...


May 28, 2007 at 12:12 PM // reply »
11,238 Comments

Thanks for your all the feedback and tips. This has all helped me to clear up the confusion in my mind. I like being able to do this.


May 29, 2007 at 10:21 PM // reply »
16 Comments

Hey Ben,

What resources (or books if any) would you be making use of to study?


May 30, 2007 at 10:16 AM // reply »
11,238 Comments

Hey fellas, could you take a quick glance at this and let me know if that graphic makes sense?

http://www.bennadel.com/index.cfm?dax=blog:737.view

Thanks for your help :)


May 30, 2007 at 10:17 AM // reply »
11,238 Comments

@William,

Honestly, I think reading the documentation is really one of the best ways to get the basic understanding of all that the language has to offer. Then, try a mini project that gets the gears working in your head. Learning by goal-oriented doing is the best.

And then, on top of that, I am always willing to write up a demo of something if you get stuff.


ben
Aug 13, 2007 at 4:53 PM // reply »
3 Comments

Hi,

Once an external class file has been instantiated through cfobject it remains cached until the CF App service is restarted. Are you aware of any way to flush out the cached class (under web-inf/classes) without restarting the CF app service?

Thanks,

Ben


Aug 14, 2007 at 5:19 PM // reply »
11,238 Comments

@Ben,

I am not sure about that. To be honest, I am not even really sure what you are talking about :) Sorry, I wish I was more help.


ben
Aug 14, 2007 at 5:36 PM // reply »
3 Comments

Sorry about the confusion. What I was asking was THAT pertinent to the topic, but I've been researching this all over and have found very little. Anyway, here is some background and what I'm trying to figure out (I'm including some sample code that you can test this with as well).

Scenario:
Create an external Class file. Copy and save the compiled file to the cf_root/wwwroot/web-inf/classes folder. Now instantiate it with cfobject. Great! You can read the file and see it via your CFM page. Now go ahead and make a change to the java file, compile it and save over the new "modified" class file to the cf_root/wwwroot/web-inf/classes folder. Run your CFML code again and it will read the initial cached file. Heck, delete your class file in the cf_root/wwwroot/web-inf/classes folder and CF will still read the cached file. The only way to force CF to read the new file is to restart the CF App service.

Here is some sample code:
Java:
===============
package ClassReload;

public class ReloadTest{
public ReloadTest(){

}
public String GetReload(){
return "This be version UNO!!";
}
}
===============

save the resulting class file to the web-inf/classes folder and run the following CF code:

<cfobject action="create" type="java" class="ClassReload.ReloadTest" name="TestClassReloading">
<cfdump var="#TestClassReloading.GetReload()#">

Great! You'll see "This be version UNO!!"

Now go ahead and change your return value to be something else "This be version TWO!!". Recompile and save to the web-inf/classes folder. Run your CF code again and you'll still see "This be version UNO!!". The only way I can see the new class file is by restarting the CF App service.

I have followed the suggestions at the following to no avail:
http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_18228&sliceId=2
or
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Java_2.html
In both cases scroll to where you see the "class loading" or "dynamic class loading" part.

Sorry for the long post, but I hope it makes sense.


ben
Aug 14, 2007 at 5:37 PM // reply »
3 Comments

Sorry, I meant it was NOT that pertinent to the topic :)



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools