Skip to main content
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with: George Murphy
Ben Nadel at cf.Objective() 2011 (Minneapolis, MN) with: George Murphy

CFCatch Can Target Explicit Java Exception Types Even With JavaLoader In Lucee 5.3.2.77

By
Published in Comments (5)

If you've been in the ColdFusion world for a while, there's a good chance that you've come across Mark Mandel's JavaLoader project. The JavaLoader project wraps a URLClassLoader, making it easy to load external Java Classes right from a set of JAR file-paths. However, there's been one long-standing issue with the JavaLoader, which is that it makes it hard to target explicit Java exception types in your cfcatch blocks. At least, this was true with Adobe ColdFusion. But, given Lucee CFML's tighter integration with Java, I wanted to see if the same issue was present in a Lucee 5.3.2.77 context.

To test this, I'm going to use the JavaLoader to create a Jedis connection pool that has an invalid host name. While the connection pool itself will be instantiated just fine, any attempt to retrieve a connection from the pool will throw a Jedis exception. And, by wrapping such a call in a try/catch, I can check to see what type of errors we can target explicitly in a catch:

<cfscript>

	// Testing to see if we can explicitly catch Java exception types when the error is
	// thrown from a class that was loaded via the JavaLoader (ie, via a URLClassLoader
	// that links to external JAR files).
	try {

		// NOTE: Expected to throw an error.
		jedis = getJedisPool().getResource();

	// Testing to see if we can explicitly catch this Java Exception by type.
	} catch ( "redis.clients.jedis.exceptions.JedisConnectionException" error ) {

		writeOutput( "<p>Caught with <strong>EXPLICIT TYPE</strong></p>" );
		writeDump( var = error, show = "type,message" );

	// .... OR, do we have to fall-back to using "any".
	} catch ( "any" error ) {

		writeOutput( "<p>Caught with <strong>ANY TYPE</strong></p>" );
		writeDump( var = error, show = "type,message" );

	}

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

	/**
	* I return a Jedis connection pool with an INVALID HOST which throw an error when
	* you try to retrieve a resource.
	*/
	public any function getJedisPool() {

		var javaLoaderFactory = new JavaLoaderFactory.JavaLoaderFactory();
		var jedisLoader = javaLoaderFactory.getJavaLoader([
			expandPath( "./commons-pool2-2.6.2.jar" ),
			expandPath( "./jedis-3.1.0.jar" )
		]);

		var config = jedisLoader.create( "redis.clients.jedis.JedisPoolConfig" ).init();	
		var pool = jedisLoader.create( "redis.clients.jedis.JedisPool" ).init(
			config,
			"this_is_not_a_valid_host_and_will_fail"
		);

		return( pool );

	}

</cfscript>

As you can see, we are providing two cfcatch blocks, one that explicitly targets exceptions of type:

redis.clients.jedis.exceptions.JedisConnectionException

And, one that targets exceptions of type:

any

Now, if I run this CFML code in Lucee CFML 5.3.2.77, we get the following browser output:

Lucee CFML is able to target an explicit Java exception type, even when the error is thrown by the JavaLoader.

As you can see, Lucee is able to explicitly target the Jedis exception type, even though the underlying error was thrown by a Java Class that was loaded via the JavaLoader / URLClassLoader.

And, if we run this same CFML code in Adobe ColdFusion 2018, we get the following browser output:

Adobe ColdFusion 2018 is unable to target the explicit Java exception type due to the use of the JavaLoader.

Ad you can see, Adobe ColdFusion 2018 is unable to target the Jedis exception type. This is because the error is being thrown by a Java Class that was loaded via the JavaLoader / URLClassLoader.

I'm really loving how much tighter Lucee's integration with Java appears to be (when compared to Adobe ColdFusion). Not only can it seamlessly load Java classes using createObject(); but, if you are using the JavaLoader project, Lucee can also more explicitly target Java exception types, regardless of where the underlying error is being thrown.

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

Reader Comments

15,811 Comments

@Charles,

Ha ha ha, Jedis is just a Java client for Redis (Java Redis -> Jedis) :D

And, if you're curious, Redis is really fast in-memory key-value database. Kind of like a ColdFusion Struct .... if you had 16GB of RAM for that one Struct. At work, we use Redis to do things like cache IP-geolocation, Session state, and rate-limiting status.

15,811 Comments

@Charles,

Redis has its own set of "commands" that you have to run. Since it's just a key-value store (with some additional Set and Pub/Sub functionality), there's nothing that relates one key to another - not like a relational database.

If you're interested, here are the Redis commands you can run:

https://redis.io/commands

I think you may actually be able to use Redis to power the distributed cache in ColdFusion ... but, I could be remembering that incorrectly.

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