Developer

ColdFusion's Java connection

Integrating Java into ColdFusion lets you access the standard Java/J2EE libraries as well as your own Java code. See how a ColdFusion developer hooks into the underlying power of Java with the help of a few simple functions.


Macromedia calls CFML "a scripting layer for J2EE." The ability to integrate Java into ColdFusion provides all sorts of opportunities, including access to freely and commercially available Java libraries; features in the standard Java and J2EE libraries; and your own Java code. In some cases, this can mean access to functionality that's simply not available in ColdFusion.

With that in mind, let's see how a ColdFusion developer hooks into the underlying power of Java with the help of a few simple functions.

Creating Java objects
We'll start with a simple Java class called SimpleMath. We're interested in its addNumbers() method (or "function" to us ColdFusion folk). Check out the Java source code in Listing A, but keep in mind that depending on how you came across the class you intend to use, you may not have access to the actual Java source code. You will, hopefully, have some documentation on how to use the compiled class.

Listing A
public class SimpleMath {
   
   publicintaddNumbers(int num1, int num2){
       
       return num1 + num2;
       
    }
}

How do we use the addNumbers() method from within our CF code? We need to use the createObject() function to tell ColdFusion that we want to use this SimpleMath class. Listing B shows how this is done.

Listing B
<!—- create an object based on the SimpleMath class  —->
<cfsetmyObject = createObject( "java", "SimpleMath" ) >
 
<!—- call the addNumbers method and store the result in a variable. —->
<cfset result = myObject.addNumbers( 25,25 ) >
 
<!—- Print the value of the variable.  —->
<cfoutput>The result is: #result#</cfoutput>

The first thing this code does is use the createObject() function to create a Java object based on the SimpleMath class. The myObject variable is simply a reference to that object. The createObject() function’s first argument is the string “java”—which signifies that we are, oddly enough, creating a Java object. The next argument, “SimpleMath”, is the name of the Java class we want to use.

After that, it's simply a matter of using dot syntax with the myObject variable to call the addNumbers() method. Keep in mind that Java is case-sensitive, so I was careful to call addNumbers() and not AddNumbers() or addnumbers().

Where Java classes live
When using classes that are not built into the standard Java libraries, ColdFusion will need to know where to look for the classes. You can use the ColdFusion administrator to add the class to your classpath, or you can put your class in a directory that is already a part of your classpath (Server settings > java and jvm > classpath).

Okay, so now we know how to use the very powerful createObject() method. Admittedly, it was not a terribly exciting example. Keep in mind, however, that this is how you would go about creating an object based on any Java class.

Constructing objects
Unlike SimpleMath, many Java classes require the use of a constructor when they are first created. Put simply, some Java classes just won't work unless you pass them one or more arguments when you create them. Consider the standard Java networking class Socket. There would be no point in a Java developer trying to do the following:
Socket sock = new Socket();

The reason is that this class needs to be passed the host name and port that this class makes use of. This particular line of Java code would cause a Java developer problems at compile time. The corrected version looks like this:
Socket sock = new Socket(“localhost”, 8080);

This Socket object has been initialized with a host and port number. In Java, this is all done when the developer creates the object with the keyword new. In ColdFusion, we handle things a little differently; we use the init() method. Listing C shows an example of how we would initialize a Java Socket object in ColdFusion.

Listing C
<!—- create an object based on the Socket class —->
<cfset sock = createObject( "java", "java.net.Socket" )>
<cfsetsock.init( "localhost", 8080)>
 
<!—- call the isConnected() method —->
<cfset success = sock.isConnected()>
 
<!—- Print the value of the variable. —->
<cfoutput>Are we connected to the localhost server on port 8080: #success#</cfoutput>

Listing C is not radically different from Listing B. This time around, I used a Java class that requires arguments in order to construct itself into a useful object. The init() method took care of this by passing along the host name and port number that the underlying Java constructor method required in order to work.

Unlike the SimpleMath class, the Socket class is a standard part of Java, so I didn't have to use the ColdFusion administrator to deal with classpath issues.

When is an object created?
You would be forgiven for thinking that the createObject() function creates an object. This isn't the case at all—it simply prepares ColdFusion for the possibility that an object might be created. One thing ColdFusion will do after a call to createObject() is check that the class you're trying to use actually exists.

So when is the object created? This happens the very first time you call one of its methods. With that in mind, you should be careful to ensure that your object is set up properly with init()before you begin using it.

It's important to understand that if you do not call the init() method after you use the createObject() method, ColdFusion will use the default constructor for the given class. This is just fine as long as the class you're attempting to use actually has a default constructor. The point is that if your class requires arguments, you must use the init() method to pass them along or ColdFusion will complain about the mistake.

Method selection problems
At this point, we know about the two main methods we need in order to work with Java classes in ColdFusion: createObject() and init(). There's another method, javaCast(), which you'll need from time to time.

ColdFusion, like most scripting languages, is weakly typed. For example, ColdFusion has just one type for working with numbers, whereas Java has several number types that the developer can choose.

Add to this the fact that Java developers are allowed to specify more than one method of the same name within the same class—a Java feature called method overloading. It's possible, even common, for these overloaded methods to have the same number of arguments yet have different "types" of arguments. Check out Listing D, which shows a Java class that has two getCommission() methods. One of these methods expects an int value, while the other expects a double.

Listing D
public class SalesCalculator{
   
   public String getCommission(intsalePrice){
       return "int version was called";
    }
   
   public String getCommission(double salePrice){
       return "double version was called";
    }
}

Here’s the problem: ColdFusion has no concept of an int or a double since it has just the one type for all kinds of numbers. The line of code below assumes we've already used createObject() and is an incorrect attempt to call one of the getCommission() methods from Listing D:
<cfset commission = mySalesCalculatorObject .getCommission(23) >

Which of the two getCommission() methods will ColdFusion call? Unfortunately, ColdFusion will call neither; instead, it will report a "method not found" or "method selection" error. To ColdFusion, both methods look identical, so it throws an error rather than try to guess what you intended. That's where javaCast() comes in to save the day. It takes two arguments. The first is the type you want ColdFusion to pass to Java; your choices are int, long, double, or string. The second argument should be the actual value you want to pass. Here is a corrected version of the previous attempt:
<cfset commission = mySalesCalculatorObject.getCommission(javaCast("int", 23) ) >

The argument being passed to getCommission() is now javaCast("int", 23). This tells ColdFusion it should call the int version of the getCommission() method.

With just a few new functions and some very basic Java knowledge, you can tap into the power and richness of ColdFusion’s underlying Java foundation. I encourage you to explore the standard Java libraries and become familiar with the ideas we've looked at here. It really is a whole new world and a great way of getting your feet wet with the Java language.

Editor's Picks

Free Newsletters, In your Inbox