Skip to main content
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Jason Kadrmas
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Jason Kadrmas ( @itooamaneatguy )

Creating Typed Java Arrays In ColdFusion Using JavaCast()

By on
Tags:

A few years ago, I created a user defined ColdFusion function - toJava() - that tried to me "smart" about the way it cast ColdFusion values into Java values. Unfortunately, it turns out that I was basically re-creating a feature that ColdFusion already had; only, I didn't really understand how it worked. I'm talking about the javaCast() function. And, more specifically, I'm talking about creating typed Java arrays using javaCast(). At the time, I didn't understand how array-casting worked. Now, years later, I think I finally get it.

I believe that the root of my misunderstanding of the javaCast() function stemmed from the fact that I wasn't thinking properly about simple data types vs. complex data types. Or, perhaps more accurately, native data types vs. class instances. When you're dealing with native data types like Booleans, Strings, and Integers, javaCast() is a lot more flexible - you just pass it an array of ColdFusion values and javaCast() will cast it properly. If you're dealing with class instances, however, javaCast() can only perform the array cast, not the individual value casts.

To demonstrate below, I'm creating typed Java arrays using both native data types and Java class instances. With the native data types, I'm showing both the simple cast (ie, the collection-only) as well as the [unnecessarily] comprehensive cast (ie, I'm casting each value individually). With the class instances, I can't use a simple cast - I have to explicitly cast each value in the ColdFusion array before I cast the entire collection.

<cfscript>

	// Byte arrays. Binary data is represented by an array of bytes.
	// And, each byte is represented by an integer. For simple values,
	// we don't have to manually cast each value - we can just pass-in
	// the array and ColdFusion will perform the cast.

	// Test 1 - Spell "SARAH" with ColdFusion numbers.

	bytes = javaCast(
		"byte[]",
		[ 83, 65, 82, 65, 72 ]
	);

	writeOutput( charsetEncode( bytes, "utf-8" ) & "<br />" );

	// Test 2 - Spell "SARAH" with Java bytes.

	bytes = javaCast(
		"byte[]",
		[
			javaCast( "byte", 83 ),
			javaCast( "byte", 65 ),
			javaCast( "byte", 82 ),
			javaCast( "byte", 65 ),
			javaCast( "byte", 72 )
		]
	);

	writeOutput( charsetEncode( bytes, "utf-8" ) & "<br />" );


	// ------------------------------------------------------ //
	// ------------------------------------------------------ //


	// Char arrays. Character arrays work the same way that byte
	// arrays work: you don't have to perform the cast manually
	// for each character - ColdFusion will do that for you. To
	// test this, we'll use a StringBuffer which can accept char[]
	// as an append() argument.

	buffer = createObject( "java", "java.lang.StringBuffer" ).init();

	// Test 1 - Add "TRICIA" with ColdFusion strings.

	buffer.append(
		javaCast( "char[]", [ "T", "R", "I", "C", "I", "A" ] )
	);

	// Test 2 - Add "TRICIA" with Java chars.

	buffer.append(
		javaCast(
			"char[]",
			[
				javaCast( "char", "T" ),
				javaCast( "char", "R" ),
				javaCast( "char", "I" ),
				javaCast( "char", "C" ),
				javaCast( "char", "I" ),
				javaCast( "char", "A" )
			]
		)
	);

	// Since we appended twice, should output "TRICIATRICIA".
	writeOutput( buffer.toString() & "<br />" );


	// ------------------------------------------------------ //
	// ------------------------------------------------------ //


	// String arrays. Although a slightly more complex data type,
	// strings work the same way that bytes and chars work. You don't
	// have to cast the individual values manually. To test this, we'll
	// use the common string utils which can accepts String[] as an
	// argument in some methods.

	utils = createObject( "java", "org.apache.commons.lang.StringUtils" );

	// Test 1 - Use ColdFusion strings.

	inputs = javaCast(
		"string[]",
		[
			"Hello world",
			"Hello there!",
			"Hell yis!"
		]
	);

	writeOutput( utils.getCommonPrefix( inputs ) & "<br />" );

	// Test 2 - Use Java strings (which are really the same thing).

	inputs = javaCast(
		"string[]",
		[
			javaCast( "string", "Hello world" ),
			javaCast( "string", "Hello cutie pie!" ),
			javaCast( "string", "Hell yis!" )
		]
	);

	writeOutput( utils.getCommonPrefix( inputs ) & "<br />" );


	// ------------------------------------------------------ //
	// ------------------------------------------------------ //


	// With simple values like integer, char, string, float, long,
	// etc., ColdFusion will create a types array and ensure that
	// each item within that array is properly casted. With complex
	// Java Class instances, things are a little less flexible. If
	// you need a typed array of some set of class instances, you
	// have to make sure that each item is *alread* in the proper
	// data type.

	// In ColdFusion, a common example of this is the need to create
	// a collection of URL[] instances for a Java class loader. First,
	// we have to create a ColdFusion array that is populated with
	// actual Java URL instances:
	urls = [
		createObject( "java", "java.net.URL" ).init(
			javaCast( "string", "file:///foo" )
		),
		createObject( "java", "java.net.URL" ).init(
			javaCast( "string", "file:///bar" )
		)
	];

	// Once we have the ColdFusion array populated with URL instances,
	// we can then cast the ColdFusion array to a typed Java array in
	// order to instantiate the class loader.
	loader = createObject( "java", "java.net.URLClassLoader" ).init(
		javaCast( "java.net.URL[]", urls )
	);

</cfscript>

The fact that ColdFusion lives on top of Java means that we have a world of powerful features laying just below the surface. Unfortunately, communication with the Java layer requires type-casting; but, luckily, ColdFusion's javaCast() function makes that a fairly easy task, once you understand how it works.

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

Reader Comments

1 Comments

Small little trick just saved me! I was having an issue with overloaded java functions that all took arrays (string[],byte[], etc) causing ColdFusion to throw multiple methods found error.

Didnt even hit me you could do a javacast of a string[]. Thank you so much!

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