Welcome!

You will be redirected in 30 seconds or close now.

ColdFusion Authors: Yakov Fain, Jeremy Geelan, Maureen O'Gara, Nancy Y. Nee, Tad Anderson

Related Topics: ColdFusion

ColdFusion: Article

A Cold Cup o' Joe

A Cold Cup o' Joe

In Part 3 of this series (CFDJ, Vol. 3, issue 4) we looked at the basics of creating and using Java objects in ColdFusion templates.

In Part 4, I discuss a number of other aspects of using Java objects in CFML as well as introduce some tools that I hope will be useful to you in debugging the Java components.

Bonus
While working on my own projects as well as this series I started to piece together a handy kit of Java classes for working with ColdFusion. The real payoff comes in the form of extending tools, two of which I'll introduce in this article: JVMLog and Debugging-Factory. These are fairly simple tools; however, they use a number of auxiliary classes that are beyond the scope of this article. I've packaged them all, in typical fashion, into a JAR that can be found on the CFDJ Web site. I'll release updates and additions to this JAR with future articles in this series. Each release is identified by month and year; this one is ccoj_042001.jar, for the April 2001 release.

Amend the CLASSPATH setting on the Java Settings panel to include this JAR.

A Confession
I lied in Part 3 of this series. It was a little white lie, but a lie nonetheless. Writing a Java class that works with ColdFusion requires some special attention. Allow me to plead my case anecdotally. One of the things I'm frequently asked is: Why doesn't my "Hello, World" program work when I call it from a ColdFusion template? Almost invariably I find that inquiring minds have constructed a valid "Hello, World" program just as they've been instructed to do in all their beginning Java books.

public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello, World");
}
}
Unfortunately, this doesn't work in ColdFusion. Remember, as I discussed in Part 3, a <CFOBJECT> or CreateObject call loads only the class and doesn't execute it until use. One of the things the Java command line interpreter will look for is a main method in the class file being executed. To add to the inquirer's frustration, the ColdFusion interpreter doesn't capture the standard output or standard error output of executing Java objects. Getting data or feedback from a Java object should happen though returned values from method calls. Designing a Java object that interacts with ColdFusion should reflect that ideal. So printing anything to System.out or System.err is verboten, strictly speaking. Thus a "Hello, World" in Java, written to be well behaved for ColdFusion, would look something like this:
public class HelloWorld
{
public String sayHello()
{
return(new String("Hello, World"));
}
}
and could be used in a ColdFusion template with a few lines:
<CFSCRIPT>
obj = CreateObject("java", "HelloWorld");
WriteOutput(obj.sayHello());
</CFSCRIPT>
Log It
While I steadfastly agree with the whole concept of well-designed classes with queryable state information, as opposed to unsolicited feedback, I felt this was a drawback. There are plenty of times when the ability to capture both the standard and error output is valuable, even if only for logging purposes. To that end I created a class that allows you to tee tap everything written to System.out and System.err and have it directed to a log.

In the JVMLog class I created you can replace the PrintStream instances used by the JVM's system object. The new PrintStream subclass that I created will allow for any data directed to it to be logged (through an Observer design pattern) before being sent to its final destinations, shown in this short <CFSCRIPT> snippet from Listing 1.

<CFSCRIPT>
log = CreateObject("java", "JVM Log");
log.init("C:\CFUSION\LOG\java.log");
</CFSCRIPT>
Naturally this is something you'll have to manually toggle on and off yourself each time the ColdFusion Server is restarted. Toggling the logging mechanism off can also be done with an equally short <CFSCRIPT> snippet from Listing 2.
<CFSCRIPT>
log = CreateObject("java", "JVM Log");
log.restore();
</CFSCRIPT>
This is really no great feat. I merely made the PrintStream subclass static members of JVMLog. The class file caching feature of the JVM did much of the work for me.

JavaCast - Overloading Revisited
In Part 3 I talked about some of the idiosyncrasies surrounding method overloading. In an effort to provide you with more help I spent a little time investigating JavaCast. Unfortunately, I didn't get the results I was expecting. According to the on-line documentation (CFML Language Reference, Chapter 2: "ColdFusion Functions, JavaCast") this function is supposed to allow the developer to overcome the problems with overloaded methods by casting variables into specific and distinguishable data types. Unfortunately, I couldn't get the example in the documentation to work without modification (for starters <CFOBJECT> doesn't appear as a two-part tag anywhere else in the CFML language documentation I've read except in this example, but I digress).

The JavaCast function takes two arguments: Type and Variable. The Type argument specifies the Java data type the CFML variable will be converted into (Boolean, int, long, double, or String); the Variable argument is the CFML variable that's to be converted.

I created a simple class called SignatureCheck (see Listing 3) that contains a method called print with several different signatures, one for each of the accepted types. Then with a template (see Listing 4) I cast a numeric CFML variable to those types. In all cases the calls to the print method of the SignatureCheck succeeded, and in all cases they called the exact same print method, the one with the primitive int as its argument.

I scratched my head for a long time on this one. Reviewing the broken sample in the JavaCast documentation, I noted the order that it listed the signatures. Interestingly enough, when I shuffled the order of the print methods in Signature-Check, I received some different results. As long as the method that took the String appeared in the source file before the others, my example partially worked. A little more shuffling, recompiling, re-starting, and head scratching and I found that getting any two of the numerical signatures to work was beyond me. Whichever one ap-peared after the String signature in the source file was the one that would get called in all cases. In frustration I even created a signature with a char (which is not one of the listed castable types) only to have a truncated number begin to appear in my browser.

It would seem that despite the documentation to the contrary, JavaCast doesn't work as advertised. Nested Objects

A common enough practice in OO projects is to have hierarchies of nested objects. Without getting into complicated code listings, we can imagine such a hierarchy as a shelf object that contains zero to many book objects, each containing zero to many pages. It's conceivable then to obtain the name of a book with the following code snippet:

shelf.getBook(2).getName();
Or the contents of a page with the following:
shelf.getBook(2).getPage(1).getText();
It could then be expected that to get the page content, a statement like this could be used in ColdFusion:
<CFSET pagecontent = shelf.getBook(2).getPage(1).getText()>
Using this syntax raises an exception. It seems that the current versions of ColdFusion can't navigate nested hierarchies at all. A series of <CFSET> statements is need to drill down, such as:
<CFSET book = shelf.getBook(2)>
<CFSET page = book.getPage(1)>
<CFSET pagecontent = page.getText()>
This can get rather tedious in deeply nested sets (though using <CFSCRIPT> blocks will cut the typing a little) and, unfortunately, there doesn't seem to be a way around this.

Catching Errors
It's always advisable to use all the error-handling capabilities available to you. The possibility that your application will do something you didn't intend under unforeseeable conditions is high, even with applications that have been thoroughly tested. To this end, Allaire has provided us with some very useful facilities. One of the more powerful ones is the structured exception handling in CFML, which will seem familiar to the Java developer. With <CFTRY> and <CFCATCH> you can intercept troublesome conditions with your Java objects.

Assuming a properly configured JVM, there are essentially two different classifications of errors that can be raised using Java. The first type are errors thrown by the CFML interpreter trying to load Java classes, create objects, or locate methods or properties in a class. The second type consists of exceptions thrown during the execution of a properly loaded and called Java class.

Both kinds of errors are demonstrated in the template (see Listing 5) using a slightly modified version of the Hello class, from Part 3 (see Listing 6). In this template I try to create an object with a misspelling in the Class parameter of <CFOBJECT>, make a method call (with a misspelling), and finally I correctly call a method whose only purpose is to raise an exception. In all three cases I display the entire CFCATCH structure (using an exceptionally useful custom tag by Nathan Dintenfass, <CF_OBJECTDUMP>, which can be found at Allaire's TagGallery), shown in Figure 1.

As you can see, the first two errors look fairly common for CFML errors, though the value of the Type key being "UNKNOWN" is troublesome. It's the third error that you're more likely to encounter. There's actually quite a bit of information to be gleaned here. The Type key has a listed value, "OBJECT"; the Message key holds the fully qualified Java exception class (in this case java.-lang.Exception); the Detail key also contains the Java exception class, a colon (if there is a message), the message sent with the raise exception, an additional period, and some additional text informing you that a Java exception occurred. I'm not overly fond of the noise in the Detail key, so within my Java code I put the message text of my exception in square brackets. This tactic allows me to dissect the string and display only the error message I really want to be displayed, as seen in this snippet:

#ListGetAt(ListGetAt(CFCATCH.Detail, 1, "]"), 2, "[")#
If you're using <CFSCRIPT> for your Java work you'll have to wrap that block inside your <CFTRY> block as <CFSCRIPT> doesn't yet support try/catch blocks.

Class Caching
One of the powerful things the ColdFusion Server does for the Java developer is to load the JVM only once. Since the JVM caches a class's bytecode, once the class is loaded all calls to it are relatively quick, thus your templates that are using Java objects should remain responsive.

The downside to this wonderful feature comes in the development phase of your Java components. Every time you update and recompile the source, you have to restart the ColdFusion Server to flush the JVM's class cache from its memory. As tedious as this is, it could almost be considered acceptable in small development efforts. However, providing hot fixes in a testing or staging environment is a completely different matter. Restarting the ColdFusion Server just to flush the JVM could be devastating to days' worth of functional or performance testing.

Keeping it simple, an exemplification of this would be to execute the following:

<CFSCRIPT>
hw = CreateObject("java", "Hello");
WriteOutput(hw.greeting());
</CFSCRIPT>
This will cause the JVM to cache the Hello class shown in Listing 6. First open the source for Hello class in your favored editor, then do a search and replace on the word "Hello," changing it to "Hi." Save, recompile, and execute the snippet again. You should see the same results. Your change won't be picked up until you restart your ColdFusion Server.

I've trolled through the documentation and the forums looking for some hint of a secret Allaire setting that would allow me to restart the JVM or flush its class loader, to no avail. I had some difficulty interpreting the documentation about how to force Java CFX tags to reload (which I'll discuss in a later article in this series), but nothing for regular Java classes. After a little thinking I came up with a simple-to-use solution - I created my own custom class loader wrapped with a class factory design pattern. This class factory (the Debugging-Factory class) stays loaded, as does the custom loader (which I made static within the factory), so a fair measure of performance is still maintained. The benefit is that the factory has a method for flushing the custom loader. What's more, the custom loader filters incoming requests so that the "primordial" class loader still handles all the classes from the default Java packages.

You can load the Debugging-Factory with the following:

<CFSCRIPT>
factory = CreateObject("java",
"net.rish.coldfusion.
util.DebuggingFactory");
</CFSCRIPT>
Using the factory to load and flush classes from its own internal class loader is simple. Review a snippet from Listing 7 below:
<CFSCRIPT>
factory = CreateObject("java",> "net.rish.coldfusion.
util.DebuggingFactory");
hw = factory.create("Hello");
WriteOutput(hw.greeting());
</CFSCRIPT>
We see the creation of the factory, a call to the factory to create the Hello class (from Listing 6), and the use of the instantiated Hello object. Execut-ing Listing 7 should show you a "Hello, World" in the browser. Pretending that this is unacceptable you can now go to Hello's class source and change the greeting method to "Hi." Recompile the Hello and hit the Refresh button on your browser. What you see is pretty much what you'd expect under normal operation - the new greeting is not displayed. But if you execute the template shown in Listing 8, the DebuggingFactory's flush method is invoked. This will clear the factory's internal class cache. Now for the real test: if you return to Listing 7 and hit the Refresh button, the new greeting should be displayed.

The class factory is generic. One of its shortcomings is that it actually instantiates the requested class. This means you can't use alternate constructors for the objects you're creating. In a real-world scenario, you'd have to implement your own or subclass this one.

Wrapping It Up
Saying that most Java developers would be comfortable with CFML would be a stretch. However, with a little understanding and a few tools, a reasonable degree of functionality can be gotten.

Standing Upon the Shoulders of Others
The JVM logging and object-caching solutions I implemented are based upon ideas from a few different places, such as the Observer and Factory design patterns. I eagerly recommend, as a good investment of time, researching these and other design patterns, which might help you construct better software or divine better solutions.

A good place to start would be with one of the most recognized book on the subject: Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma et al (Addison-Wesley). It's not a quick read, nor is it a onetime read. It's the jumping-off point for years of research and application. While it's targeted for folks doing object-oriented programming, I've found it's still applicable to any kind of software development effort.

More Stories By Guy Rish

Guy Rish is a ColdFusion and .NET developer at Vente as well as President at Gestaltech. He is an active developer and writer for various languages and technologies, and has contributed work in books on ColdFusion MX, Flash MX, and Dreamweaver MX. He blogs at ccoj.coldfusionjournal.com.

Comments (2) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
ben 08/14/07 12:19:11 PM EDT

The associated zip files are no longer on the server for download. Can you please repost!

Denis Pouliot 06/06/03 05:05:00 PM EDT

I would like to obtain this file (or newer one), but I can't find it....

Thanks in advance...

@ThingsExpo Stories
Elon Musk is among the notable industry figures who worries about the power of AI to destroy rather than help society. Mark Zuckerberg, on the other hand, embraces all that is going on. AI is most powerful when deployed across the vast networks being built for Internets of Things in the manufacturing, transportation and logistics, retail, healthcare, government and other sectors. Is AI transforming IoT for the good or the bad? Do we need to worry about its potential destructive power? Or will we...
SYS-CON Events announced today that SIGMA Corporation will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. uLaser flow inspection device from the Japanese top share to Global Standard! Then, make the best use of data to flip to next page. For more information, visit http://www.sigma-k.co.jp/en/.
SYS-CON Events announced today that Daiya Industry will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Daiya Industry specializes in orthotic support systems and assistive devices with pneumatic artificial muscles in order to contribute to an extended healthy life expectancy. For more information, please visit https://www.daiyak...
SYS-CON Events announced today that B2Cloud will exhibit at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. B2Cloud specializes in IoT devices for preventive and predictive maintenance in any kind of equipment retrieving data like Energy consumption, working time, temperature, humidity, pressure, etc.
SYS-CON Events announced today that Massive Networks, that helps your business operate seamlessly with fast, reliable, and secure internet and network solutions, has been named "Exhibitor" of SYS-CON's 21st International Cloud Expo ®, which will take place on Oct 31 - Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. As a premier telecommunications provider, Massive Networks is headquartered out of Louisville, Colorado. With years of experience under their belt, their team of...
SYS-CON Events announced today that NetApp has been named “Bronze Sponsor” of SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. NetApp is the data authority for hybrid cloud. NetApp provides a full range of hybrid cloud data services that simplify management of applications and data across cloud and on-premises environments to accelerate digital transformation. Together with their partners, NetApp em...
SYS-CON Events announced today that Interface Corporation will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Interface Corporation is a company developing, manufacturing and marketing high quality and wide variety of industrial computers and interface modules such as PCIs and PCI express. For more information, visit http://www.i...
SYS-CON Events announced today that Mobile Create USA will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Mobile Create USA Inc. is an MVNO-based business model that uses portable communication devices and cellular-based infrastructure in the development, sales, operation and mobile communications systems incorporating GPS capabi...
SYS-CON Events announced today that Nihon Micron will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Nihon Micron Co., Ltd. strives for technological innovation to establish high-density, high-precision processing technology for providing printed circuit board and metal mount RFID tags used for communication devices. For more inf...
SYS-CON Events announced today that N3N will exhibit at SYS-CON's @ThingsExpo, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. N3N’s solutions increase the effectiveness of operations and control centers, increase the value of IoT investments, and facilitate real-time operational decision making. N3N enables operations teams with a four dimensional digital “big board” that consolidates real-time live video feeds alongside IoT sensor data a...
SYS-CON Events announced today that Suzuki Inc. will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Suzuki Inc. is a semiconductor-related business, including sales of consuming parts, parts repair, and maintenance for semiconductor manufacturing machines, etc. It is also a health care business providing experimental research for...
While some developers care passionately about how data centers and clouds are architected, for most, it is only the end result that matters. To the majority of companies, technology exists to solve a business problem, and only delivers value when it is solving that problem. 2017 brings the mainstream adoption of containers for production workloads. In his session at 21st Cloud Expo, Ben McCormack, VP of Operations at Evernote, will discuss how data centers of the future will be managed, how th...
SYS-CON Events announced today that Ryobi Systems will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Ryobi Systems Co., Ltd., as an information service company, specialized in business support for local governments and medical industry. We are challenging to achive the precision farming with AI. For more information, visit http:...
SYS-CON Events announced today that MIRAI Inc. will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. MIRAI Inc. are IT consultants from the public sector whose mission is to solve social issues by technology and innovation and to create a meaningful future for people.
SYS-CON Events announced today that mruby Forum will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. mruby is the lightweight implementation of the Ruby language. We introduce mruby and the mruby IoT framework that enhances development productivity. For more information, visit http://forum.mruby.org/.
SYS-CON Events announced today that Fusic will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Fusic Co. provides mocks as virtual IoT devices. You can customize mocks, and get any amount of data at any time in your test. For more information, visit https://fusic.co.jp/english/.
In his session at @ThingsExpo, Greg Gorman is the Director, IoT Developer Ecosystem, Watson IoT, will provide a short tutorial on Node-RED, a Node.js-based programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. It provides a browser-based editor that makes it easy to wire together flows using a wide range of nodes in the palette that can be deployed to its runtime in a single-click. There is a large library of contributed nodes that help so...
SYS-CON Events announced today that Enroute Lab will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Enroute Lab is an industrial design, research and development company of unmanned robotic vehicle system. For more information, please visit http://elab.co.jp/.
Agile has finally jumped the technology shark, expanding outside the software world. Enterprises are now increasingly adopting Agile practices across their organizations in order to successfully navigate the disruptive waters that threaten to drown them. In our quest for establishing change as a core competency in our organizations, this business-centric notion of Agile is an essential component of Agile Digital Transformation. In the years since the publication of the Agile Manifesto, the conn...
Real IoT production deployments running at scale are collecting sensor data from hundreds / thousands / millions of devices. The goal is to take business-critical actions on the real-time data and find insights from stored datasets. In his session at @ThingsExpo, John Walicki, Watson IoT Developer Advocate at IBM Cloud, will provide a fast-paced developer journey that follows the IoT sensor data from generation, to edge gateway, to edge analytics, to encryption, to the IBM Bluemix cloud, to Wa...