Java Integration
Last updated
Last updated
Ortus Solutions, Corp
,CFML is compiled to Java bytecode and runs on the JVM. This gives CFML a unique advantage that not only can you write CFML but you can also integrate with the running JDK libraries or any Java library you tell the engine to use. This is great, because if there is something already written in Java, just drop it in and use it, well most of the time :) Unless Jar loading hell occurs.
CommandBox even allows you to install jar's from any endpoint into your projects: https://commandbox.ortusbooks.com/package-management/code-endpoints/jar-via-http
The easiest way to integrate with Java is to be able to instantiate Java objects or call Java static methods on objects. You will do this via the createObject()
or the new
operator approach. Here is the signatures for both approaches:
Examples:
You must remember that Java is a static and typed language. CFML is not! If you need to pass in arguments to Java functions that require native types you will have to cast them. We will use the fancy JavaCast()
function built-in to the language.
The javaCast()
method takes in two arguments:
type
: The type of casting
variable
: The value to cast
The available casting types are:
boolean
double
float
int
long
string
null
byte
bigdecimal
char
short
If you need to cast the type but as an array then you can use the []
in the casting construct. Let's create a stream from an incoming list of values and cast them to an array of objects in Java.
Ohh the dreaded day nulls where created. The variable that means that nothing exists. If you need to pass null into Java object calls then you have two approaches to create them:
The createObject( "java" )
method will look into the CFML engine's class loader to discover the class you request. If the class is not located an exception is thrown that the class could not be found. If you want to integrate with third-party Jar's and libraries then you will need to tell the engine where to look for those classes. There are essentially three ways to add custom libraries to the CFML engine:
Add the jars/libs to the CFML Lib paths. These are those obscure directories both Adobe and Lucee give you so you can drop your libraries and the engine's class loader can well, load them. Each engine has different paths, please see their docs on the matter. We won't cover this approach as it is incredibly rigid:
The Application.cfc
allows you to declare a this.javaSettings
struct where you can declare an array of locations of the libraries to load upon application startup with some nice modifiers. This will allow you to store and even leverage CommandBox for the management of such jars.
In Lucee, the createObject( "java" )
construct allows you to pass in a third argument which can be a location or an array of locations of libraries to class load. This is also great for custom CFCs, task runners, or isolated class loading.
This Application.cfc
structure takes in 3 keys that will allow you to class load any jar/.class libraries into the running ColdFusion application:
Key
Description
loadPaths
An array of paths to the directories that contain Java classes or JAR files.You can also provide the path to a JAR or a class. If the paths are not resolved, an error occurs.
loadColdFusionClassPath
Indicates whether to load the classes from the ColdFusion lib directory. The default value is false.
reloadOnChange
Indicates whether to reload the updated classes and JARs dynamically, without restarting ColdFusion. The default value is false.
watchInterval
Specifies the time interval in seconds after which to verify any change in the class files or JAR files. This attribute is applicable only if the reloadOnChange attribute is set to true. The default value is 60 seconds.
watchExtensions
Specifies the extensions of the files to monitor for changes. By default, only .class and .jar
files are monitored.
Once that is declared in your Application.cfc and you execute a createobject()
with a class from those libraries, ColdFusion will know about them and create them.
The other approach is to leverage the createObject()
call to do class loading. Please note that only Lucee supports this feature as of now.
Both ColdFusion engines also allows you to create dynamic proxies from existing ColdFusion Components (CFCs). What this means is that a Dynamic proxy lets you pass ColdFusion components to Java objects. Java objects can work with the ColdFusion components seamlessly as if they are native Java objects by implementing the appropriate Java interfaces. You can even use them to simulate Java lambdas as ColdFusion components.
If you want to leverage a Java library that requires a certain type of Java object as an argument and instead of you creating that object in Java, you can see if that argument adheres to a certain interface and CFML will create a dynamic proxy that binds it.
Basically, your CFC must implement the appropriate methods the interface(s) tell you that it needs. After that, your CFC will be Javafyied, and it can be used like a native Java interface implementing objects! Enjoy!