Creating Java Classes From JAR Files In Adobe ColdFusion 2025
For years, Lucee CFML has had the ability to load Java classes from JAR files using the built-in createObject()
function. It did this by allowing a JAR file, or collection of JAR files, to be passed-in as a 3rd argument. I'm so freaking excited that Adobe ColdFusion 2025 is now compatible with this approach.
Before Adobe ColdFusion 2025, if you wanted to create an isolated class loader, you'd have to use something like Mark Mandel's Java Loader. Which means that in order to make CFML code portable in both Adobe ColdFusion and Lucee CFML, you either had to make Lucee use the Java Loader project unnecessarily; or, you'd have to factor-out the class-loading mechanics and then use dependency-injection to provide the right class-loader at runtime.
But, with the Adobe ColdFusion 2025 update, both engines can now use createObject()
in the same way! To demonstrate, I'll render a one-dimensional barcode using the Zxing Java project. This requires two JAR files, both of which will be passed-in as the 3rd argument in the createObject()
call:
<cfscript>
/**
* I create a Java class from the given JAR files using an isolated classloader.
*
* WOOT: This now works in both Lucee CFML and Adobe ColdFusion 2025!
*/
private any function fromJars( required string classname ) {
var jarPaths = [
expandPath( "./vendor/com.google.zxing/3.5.3/core-3.5.3.jar" ),
expandPath( "./vendor/com.google.zxing/3.5.3/javase-3.5.3.jar" )
];
return createObject( "java", classname, jarPaths );
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
// Create the Java class from the JAR files above.
pixels = fromJars( "com.google.zxing.oned.Code39Writer" )
.encode( "Wooty!" )
;
// Get the CFML engine currently running.
product = server.keyExists( "lucee" )
? "Lucee CFML #server.lucee.version#"
: "Adobe ColdFusion #server.coldfusion.productVersion#"
;
</cfscript>
<cfoutput>
<h1>
#encodeForHtml( product )#
</h1>
<!--- Note: CSS (flexbox) omitted from demo. --->
<figure class="barcode">
<cfloop array="#pixels#" index="pixel">
<span data-on="#serializeJson( pixel )#"></span>
</cfloop>
</figure>
</cfoutput>
As you can see in the ColdFusion code, the fromJars()
user-defined function (UDF) is just a proxy to the createObject()
call that bakes-in the JAR file paths implicitly. Now, we can run this CFML code in both Adobe ColdFusion 2025 and Lucee CFML:

This is honestly one of if not the most exciting update for me in Adobe ColdFusion 2025. I've been so thankful to have Mark's Java Loader project available for the last 15 years. But, I'm even more thankful to not need it anymore.
this.JavaSettings
?
Why Not ColdFusion has several different ways to integrate Java into a CFML project. One way is to provide additional JAR paths in the Application.cfc
per-application settings using this.javaSettings
. The reason I tend to shy away from this approach is because it doesn't create an isolated class loader - it affects the entire application. Which means, if you have two Java dependencies that needed two different version of the same "Logging utility", you'd run into a conflict that would be hard to resolve.
lib
Folder?
Why Not Add JAR Files to the For the same reason as above: it's too broad a blast radius. When you add JAR files to a lib
folder, those files are now available to the entire ColdFusion server. Which, again, means that you'll almost certainly run into conflicts at some point.
Want to use code from this post? Check out the license.
Reader Comments
I'm no java expert but unfortunately I don't think this completely avoids the class conflict issue. It didn't with Lucee and I doubt it would be any different with ACF (although happy to be shown otherwise).
My admittedly limited understanding is that even if there's a separate classloader this will still defer to the parent classloader, and if that has a different version of the class in question there could still be a clash.
Lucee 6+ now lets you load jars directly from Maven and at the component level (i.e. javasettings in the cfc!), also with an apparently "isolated" class loader. I was really excited about this until I found it wasn't isolated at all, and my chosen version was being ignored in favour of one Lucee already had loaded.
@Julian,
Oh interesting! I am very much not a Java developer; so it's almost certain that I'm missing some of the lower-level details. And, I literally just learned about the CFC-level class loading from Zac like last week 😂 (Lucee only).
That said, I'm trying to think if I've run into that issue. I feel like I've been able to load conflicting versions of stuff with the
createObject()
in Lucee; but, I can't think of a specific thing. I think maybe I've had to load a unique version of the SL4J no-op logger for something.I'll keep my eye open for this, though. Thanks for potential pit-falls.
@Ben, yes it's only likely to be an issue if you're loading a library that ACF or Lucee happens to be using already with a different version. In my case it was Apache Tika.
As a side-note, that seems like a cool Apache library!
Nothing to add to the conversation...I'm just wishing I could react to existing comments with a thumbs-up, heart, etc. Sometimes, the comments are as interesting as the article :)
I've always found the DX of loading java classes in CF to be confusing, and I (always) have to refer back to the documentation as I do it so seldomly. So, this feels like a huge leap forward!
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →