Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2018 (Hollywood, CA) with: Jeremy Mount
Ben Nadel at InVision In Real Life (IRL) 2018 (Hollywood, CA) with: Jeremy Mount

How ColdFusion CreateObject() Really Works With Java Objects

By
Published in Comments (13)

I use ColdFusion's CreateObject() method at least a dozen times each day to create wonderful Java objects like String Buffers and File Input Stream. Until recently, I have never really thought about how it actually works - I have just accepted that the black magic under the hood did the job properly. But then, just the other day, I discovered that you could instantiate multiple Java instances off of the same Java class returned by CreateObject():

<!--- Get the string buffer class object. --->
<cfset objStringBuffer = CreateObject(
	"java",
	"java.lang.StringBuffer"
	) />

<!---
	From the string buffer class object, instantiate
	two sepparate instances of the Java string buffer.
--->
<cfset objDataOne = objStringBuffer.Init() />
<cfset objDataTwo = objStringBuffer.Init() />

When I saw this, I realized that I had no idea how ColdFusion's CreateObject() functionality really worked. After some posting and some back and forth comments, Sammy Larbi, Rupesh Kumar, and Sean Corfield have really helped to clear things up:

ColdFusion CreateObject() Functionality For Java

Apparently, when you call ColdFusion's CreateObject() method to create a Java object, ColdFusion is returning a proxy object to that Java object, not the Java object itself. This proxy object allows you to reference static properties and invoke static methods of that Java class without actually having to instantiate the full Java class. This is good for memory usage and for performance (object instantiation is a costly process).

If you call Init() on that proxy object, it then instantiates the Java object with the given arguments and returns a proxy object wrapped around this new instance (I suspect from the Init() example above that it must create a new proxy object otherwise you probably wouldn't be able to call Init() twice on the same ColdFusion proxy). Similarly, if you attempt to call a non-static method of the Java class, the proxy object will, behind the scenes, call Init() on the Java class (passing no arguments), and use that as the target class going forward.

Of course, this is what I think I understand. This may contain errors and if I get feedback on this, I will update the graphic as necessary. Thanks to all who helped me get this far.

Want to use code from this post? Check out the license.

Reader Comments

8 Comments

you can also create WebService objects this way.

i.e.:
<cfscript>
dynamicsWS = CreateObject("webservice", "http://192.168.0.100/DynamicsGPWebServices/DynamicsGPService.asmx?WSDL");
</cfscript>

<cfinvoke webservice="#dynamicsWS#" method="GetCompanyList" refreshWSDL="yes" timeout="30" returnvariable="result">
</cfinvoke>

This creates WebService object in your ColdFusion instance (available from administration panel -> webservices) and this object "lives" in there for about 10 (gets deleted if not used).

So I never took CreateObject() for granted :)

15,848 Comments

@Dmitry,

Word up - createObject() can do a whole bunch of things. It's probably one of the best updates to the language.

10 Comments

Ben, sheds some light on the subject for me. I've recently ventured into a shared hosting enviroment to do some outside work, and quickly ran into the java object disabled issue.

I'm not much of a programer, more a manager and integrator and struggling to find a workaround for some open source I'm using.

Thanks for the overview.

15,848 Comments

@Scott,

Glad you liked it. I'm sorry to hear that your Java objects have been disabled on the host. That can definitely get annoying :(

1 Comments

One quick point: I'm less certain that "object instantiation is a costly process" - object instantiation is strongly optimized on the JVM, and even reflection has far less cost than before.

IMO, the reason for the init pattern is to allow access to statics with less hoops; though this creates a somewhat schizophrenic API.

Nitpicks aside, thanks for another clear and lucid explanation of one of the details of the CF platform. Your blog has been extremely helpful to me as I learn!

1 Comments

I know this is a bit of an old thread, but I recently discovered something relevant. The init() function call on CF proxy objects is not thread safe.

Recently we began having random documents inserted into the incorrect collection on our MongoDB. We tracked it down to our own Mongo driver which leverages the Mongo Java driver as a singleton. However, in concurrency situations, creating new instances of our java class using the above method caused us sometimes to get the wrong instance back.

For example:
Process A calls init("collection1")
Process B calls init("collection2")
Both calls return CF proxy objects with the same instance of our CFMongo class pointing to collection2.

So if you are going to cache your static class in a shared location, like the application scope, you need to only call init() with an exclusion lock. In our case we chose to use CreateObject() each time passing the mongo driver singleton into the constructor.

2 Comments

Hi Ben, interesting post.

It looks like I'm running into the CF proxy object as an issue on a routine I'm writing.

I'm importing the Amazon Web Services SDK for Java into a CFC and to initialise the S3 Client you first have to create an authentication object. However passing this object (which is created correctly) to the init() function throws an "An exception occurred while instantiating a Java object. The class must not be an interface or an abstract class" error.

I'm guessing that because this isn't a true Java object the second class doesn't like it?

Anyway here's the code:

awsCred = createobject('java',
		'com.amazonaws.auth.BasicAWSCredentials').init(
		accessKey,
		secretKey
		);
// this works fine; CFDUMP shows correctly instantiated object
 
	s3 = CreateObject(	'java',
		'com.amazonaws.services.s3.AmazonS3Client'
		).init(awsCred);
// this line throws the error

Any ideas how to instantiate a real Java object?

Thanks
James

2 Comments

Ignore my earlier post, it appears that the Amazon SDK requires some more third party Jar files in the class path than it comes with, namely httpclient-4.1.1.jar if you're having similar problems.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel