Using Java Class Objects


ColdFusion allows you to work with nearly any Java class. This means you can use the functionality provided by:

  • The built-in classes provided in the Java 2, Standard Edition (J2SE) specification, including the members of such commonly used packages as java.io, java.net, and java.lang.

  • The built-in classes provided in the Java 2, Enterprise Edition (J2EE) specification, including the members of javax.ejb, javax.sql, and javax.security.

  • Other Java classes that you write yourself or obtain from a third party.

If you have already read Chapter 26, "Extending ColdFusion with COM," or Chapter 28, "Extending ColdFusion with CORBA," you are already familiar with the <cfobject> tag and the CreateObject() function. As you learned in those chapters, a call to <cfobject> or CreateObject() is always the first step when working with COM or CORBA objects. <cfobject> and CreateObject() both do the same thing: return an instance of the desired object. You then work with that instance in your ColdFusion code, generally by calling whatever methods (functions) the object provides.

Working with Java objects is not much different. First, you create an instance of the object with <cfobject> or CreateObject(). Then you call the object's methods (or work with its properties). In other words, the mechanics of dealing with any external object in ColdFusion is the same, regardless of whether the object has its roots in COM, CORBA, or Java.

Table 29.1 shows the syntax for the <cfobject> tag as it pertains to Java objects.

Table 29.1. <cfobject> Tag Syntax for Java Objects

ATTRIBUTE

DESCRIPTION

ACTION

Required, but the value must always be Create. There is no Connect action for Java objects as there is for COM objects (discussed in Chapter 26).

TYPE

Must be Java in order to connect to a Java object. The object can be an ordinary class or a Bean.

CLASS

The name of the Java class you want to use, including the appropriate package name. The class must be available somewhere in the Class Path shown in the Java and JVM page of the ColdFusion Administrator. Like most things in Java, the class name is case-sensitive, so make sure to get the name exactly right.

NAME

The variable name that you want to use for interacting with the new instance of the object.


The CreateObject() function can be used as an alternative to <cfobject>. Both do the same thing. Table 29.2 shows the CreateObject() syntax for working with Java objects.

Table 29.2. CreateObject() Syntax for Java Objects

ATTRIBUTE

DESCRIPTION

type

Must be Java in order to connect to a Java object. The object can be an ordinary class or a Bean.

class

The name of the Java class you want to use.


The fact that you can call arbitrary Java classes using the syntax shown in Tables 29.1 and 29.2 means that you have an enormous amount of flexibility when it comes to the number of tools at your disposal for creating applications with ColdFusion. If you find yourself in a situation where ColdFusion doesn't provide a tag or function to fulfill a particular need, you can literally crack open a Java reference as a source of potential solutions. If you find that Java provides a class that does what you need, just instantiate the class with <cfobject> or CreateObject(), and then start calling whatever methods you need.

Instantiating Objects and Calling Methods

Let's look at a simple example of using the underlying Java platform to perform a useful function. Suppose you're building an application that requires a user to log in to gain access to their account information, but your manager is worried about automated "brute force" attacks on the site. Your manager has called for a five-second time limit between login attempts. Since there is no ColdFusion "wait" tag, you need to figure out another way to design this requirement. This is a situation where you can call in the underlying Java foundations.

The Java API defines a thread class that has a method allowing you to make the currently executing thread "sleep" (temporarily cease execution) for a specified number of milliseconds. That method is perfect for what you need to do in this example. To call it, all you have to do is this:

 <cfobject  type="java"  action="create"    name="thread"> 

And we can do the same thing using CreateObject():

 <cfset thread = CreateObject("java", "java.lang.Thread")> 

Then to simply call the class and its method, you can do this:

 <cfset thread.sleep(5000)> 

A more complete test to see it working in action is demonstrated in Listing 29.1.

The <cftimer> tag is just there to make sure that the thread is taking a nap for the defined five seconds. So, as you can see, working with Java from ColdFusion MX 7 is amazingly simple!

Listing 29.1. JavaObjectsleep.cfmCalling a Java Class's Methods
 <cftimer label="I am a sleepy thread" type="outline">        <cfset thread = CreateObject("java", "java.lang.Thread")>        <!--- Stop processing for 5 seconds -        Thread is sleeping<br>        <cfflush>        <cfset thread.sleep(5000)>        Thread is awake again<br> </cftimer> 

NOTE

The Java language is case-sensitive, so the names of the methods you use must be capitalized correctly when they appear in ColdFusion code. In this case, that means sleep will work but SLEEP or Sleep will not. In contrast, because it is a CFML variable, the name of the tHRead variable is not case-sensitive, so you could type thread.sleep() or Thread.sleep(). This can get a bit confusing, so you should get in the habit of checking the case of the Java objects you're working with.


Listing 29.1 puts these lines into a simple ColdFusion template. When you view the page in a browser you should see something like the image in Figure 29.1.

Figure 29.1. An example of using a Java class to make a thread pause execution.


By the way, ColdFusion MX 7 also allows you to call a method directly on the result of the CreateObject() function. Feel free to use syntax like the following if you're only going to call one method and thus have no need to hold on to the object instance itself:

 <cfset NewStr = CreateObject("Java", "java.lang.Thread").sleep(5000)> 

<cfobject> and CreateObject(): Separated at Birth?

In this chapter and the two that came before it, you've been learning about <cfobject> and CreateObject(), two syntaxes for doing the same thing: instantiating an object. Why are there two competing ways to create objects, anyway? Are they redundant?

The reason is this: At first, there was only the <cfobject> tag, which previously was only for working with COM objects. It was familiar and intuitive for CFML coders, but it didn't look familiar to people coming to ColdFusion from other COM-friendly environments such as Visual Basic and ASP. That's why the CreateObject() function was added a bit later on, to make things more familiar to those people (it looks and behaves much like ASP's method of the same name).

Later, with the introduction of user-defined functions (which could only be created in <cfscript> blocks at first), CreateObject() became more popular because it was the only way to interact with objects within script, and thus the only way to do so within a UDF. As of ColdFusion MX 6, you could create functions using the superior <cffunction> tag.

This has left CreateObject() looking more like a shortcut for <cfobject> than anything else. Neither syntax seems to have more of a raison d'etre than the other. Many developers, though. find CreateObject() to be more intuitive when working with Java objects because there are only two arguments. For COM and CORBA objects, you may find <cfobject> to be more straightforward, since there are more options involved. Use whatever syntax you prefer.

Working with Constructors

Every Java class has at least one constructor. A constructor is a special method that initializes an object and places it in a valid state. In Java programming, you nearly always create a new instance of a class by calling the appropriate constructor in conjunction with Java's new keyword. In CFML, constructors are called automatically behind the scenes for you after you use <cfobject> or CreateObject().

Here's how it works. When you create an object instance with <cfobject> or CreateObject(), ColdFusion gets ready to create an instance of the class (by checking for the class's existence) but doesn't go so far as to create the new instance. Instead, ColdFusion waits for you to actually use one of the object's methods (such as the sleep() method used in Listing 29.1). As soon as your code calls a method, ColdFusion creates the instance of the class by calling the class's default constructor, then calls the requested method on the new instance.

Java classes, though, often have more than one constructor. For instance, one constructor might not take any arguments, while another might allow the new instance to be initialized with some kind of value; another might allow the new instance to be initialized with two or three more specific values.

Consider a fictional Java class called ChevyNova. This class supports three different constructors. The first constructor doesn't take any arguments. The second one accepts the color, and another accepts the color plus the number of doors. In normal Java programming, these constructors might be called as follows:

 ChevyNova myNova = new ChevyNova(); ChevyNova myRedNova = new ChevyNova("red"); ChevyNova myRedNovaHatchback = new ChevyNova("red", 5); 

When you use this same object in a ColdFusion page, the default constructor (the first one, the one without any arguments) will always be called automatically the first time you actually use the object. Some classes won't be able to work the way you want them to if the default constructor is called; in this example, there might not be any other way to establish the car's color or number of doors.

How do you call one of the other constructors? ColdFusion allows you to call specific constructors through the ColdFusion function init(). The ColdFusion init() function calls the new function on the Java class constructor. You can use the init() function anytime after the <cfobject> or CreateObject() that creates the object variable, but before you actually use one of the object's methods. When you use init(), ColdFusion tries to find the appropriate constructor to use based on the number and data types of the arguments you pass to init().

So, the ColdFusion equivalent of the earlier Chevy Nova snippet would be this:

 <cfset myNova = CreateObject("Java", "ChevyNova")> <cfset myRedNova = CreateObject("Java", "ChevyNova")> <cfset myRedNova.init("red")> <cfset myRedNovaHatchback = CreateObject("Java", "ChevyNova")> <cfset myRedNovaHatchback.init("red", 5)> 

Or, if you prefer using <CFSCRIPT> syntax, this:

 <cfscript>  myNova = CreateObject("Java", "ChevyNova");  myRedNova = CreateObject("Java", "ChevyNova");  myRedNova.init("red");  myRedNovaHatchback = CreateObject("Java", "ChevyNova");  myRedNovaHatchback.init("red", 5); </cfscript> 

In ColdFusion MX 7, you can create the new instance and call init() all at once, if you wish. It's not appreciably more efficient, but depending on your sensibilities it may seem cleaner or more intuitive. For instance, to call the three variations of the ChevyNova constructor, you could use lines like these:

 <cfset myNova = CreateObject("Java", "ChevyNova")> <cfset myRedNova = CreateObject("Java", "ChevyNova").init("red")> <cfset myRedNovaHatchback = CreateObject("Java", "ChevyNova").init("red", 5)> 

And here's the <CFSCRIPT> equivalent:

 <cfscript>  myNova = CreateObject("Java", "ChevyNova");  myRedNova = CreateObject("Java", "ChevyNova").init("red");  myRedNovaHatchback = CreateObject("Java", "ChevyNova").init("red", 5); </cfscript> 

There are two side effects of this init() mechanism:

  • If a class doesn't have what ColdFusion calls a default constructor (that is, if there are no forms of the constructor that accept zero arguments), then you must use init() to specify the specific information with which to initialize the new instance.

  • If the class actually exposes a normal method named init(), you won't be able to call it from ColdFusion. The method would have to be renamed before you could use it. If that's not under your control, one workaround would be to compile a quick subclass that exists only to expose the init() method under some other name.

Listing 29.2 shows how the init() method can be used with an actual Java class. This example uses the StringTokenizer class from the java.util package (part of the standard Java 2 API) to loop over a series of "tokens" in a string (Figure 29.1). The effect is very similar to a <cfloop> block that uses a LIST attribute.

Listing 29.2. JavaObjectStringTokenizer.cfmCalling a Specific Constructor with init()
 <!---  Filename: JavaObjectStringTokenizer.cfm  Author: Nate Weiss (NMW)  Purpose: Demonstrates how to supply arguments to a class's constructor ---> <html> <head><title>String Tokenizer Example</title></head> <body> <!--- Create an instance of StringTokenizer ---> <cfset tokenizer = CreateObject("Java", "java.util.StringTokenizer")> <!--- Pass information to the object's constructor ---> <cfset tokenizer.init("Sleater-Kinney rules!")> <!--- Now the object's methods can be used as expected ---> <ol> <cfloop condition="tokenizer.hasMoreElements()">   <cfoutput><li>#tokenizer.nextElement()#</li></cfoutput> </cfloop> </ol> </body> </html> 

First, an instance of StringTokenizer called tokenizer is prepared, using the usual CreateObject() syntax. Then init() is used to supply a string to the constructor; it's at this moment that the new instance is actually created. If this were Java code, those two lines would be replaced with:

 StringTokenizer tokenizer = new StringTokenizer("Sleater-Kinney rules!"); 

You can call constructors that accept several arguments by providing the corresponding number of arguments to init(). For instance, you could replace the init() line in Listing 29.2 with the following, which specifies the space and hyphen characters as token delimiters (basically the same as list delimiters in CFML). Sleater and Kinney would then be recognized as two separate words, rather than one:

 <cfset tokenizer.init("Sleater-Kinney rules!", " -")> 

In any case, once an object has been initialized properly, its methods can be called to get the desired behavior. In the case of StringTokenizer, there are only two available methods: nextElement(), which returns the next item in the sequence, and hasMoreElements(), which returns true until the last item has been returned. For details, consult a Java reference.

A Practical Example: Resizing Images

Let's assume you are working on a project where you have to create something like a photo album where users can upload an image and the application will automatically create a thumbnail for them. This is something you cannot actually do directly from ColdFusion. To address this requirement, we'll not create a full-blown photo application; rather, we'll create the code necessary to take a list of files from a directory, resize them as thumbnails, and save them. As we do this, you'll see in action a couple of concepts that will help you in the future when you make extensive use of specific Java classes.

With this in mind, let's introduce a best practice when deploying a Java class that you want to reuse in a ColdFusion application.

Hiding Java Code in Friendlier Wrappers

Many ColdFusion developers find Java intimidating, and a typical development group will include developers with various skill levels. For this reason you may wish to have the code you use to work with Java classes "wrapped" within a ColdFusion Component (CFC), or a UDF or custom tag. This wrapper provides a less intimidating and more consistent CFML interface.

For our photo album application, we're going to take advantage of the Java.io.File class from the Java 1.4 SDK. The first CFC we'll use will simply wrap the initialization of the java.io.File object (Listing 29.3).

Listing 29.3. JavaFile.cfcEncapsulating Java integration.
 <cfcomponent>   <cffunction name="getFileObject" access="package">     <cfargument name="filePath" type="string" required="Yes">     <!--- File for reading --->     <cfset var result = CreateObject("java", "java.io.File")>     <cfset result.init(filePath)>     <!--- Return the result --->     <cfreturn result>   </cffunction> </cfcomponent> 

This CFC, in webroot\JavaInteg folder, is simply demonstrating that common Java-related requests can be placed in a base CFC, which other Java-empowered CFCs extend. In this case, the base CFC has just one method, getFileObject(), which returns an instance of java.io.File. By extending this component from another CFC, you can inherit the method. Our next CFC (Listing 29.4) will actually do most of the real work.

Listing 29.4. ImageManipulator.cfcUsing Java functionality to manipulate images.

[View full width]

 <cfcomponent extends="JavaFile">   <!--- PUBLIC FUNCTION --->   <!--- Resizes an image --->   <cffunction name="createResizedImage" output="No" returntype="void">     <cfargument name="sourcePath" type="string" required="Yes">     <cfargument name="destPath" type="string" required="Yes">     <cfargument name="newWidth" type="numeric" required="Yes">     <cfargument name="newHeight" type="numeric" required="No" default="-1">     <!--- Get handle on the static ImageIO class --->     <cfset var ImageIO = CreateObject("java", "javax.imageio.ImageIO")>     <!--- Create target image object --->     <cfset var jbiDest = CreateObject("java", "java.awt.image.BufferedImage")>     <!--- Create image-transformation object --->     <cfset var jatTransformer = CreateObject("java", "java.awt.geom.AffineTransform")>     <!--- Get Java-style File object for reading --->     <cfset var jfileIn = getFileObject(sourcePath)>     <!--- Get Java-style File object for writing --->     <cfset var jfileOut = getFileObject(destPath)>     <!--- Read image (as instance of java.awt.image.BufferedImage) --->     <cfset var jbiSource = ImageIO.read(jfileIn)>     <!--- Get current width and height --->     <cfset var sourceWidth = jbiSource.getWidth()>     <cfset var sourceHeight = jbiSource.getHeight()>     <!--- Determine amount to scale in X direction --->     <cfset var scaleX = newWidth / sourceWidth>     <!--- Determine amount to scale in Y direction --->     <cfset var scaleY = newHeight / sourceHeight>     <!--- Allow user to provide only width; we'll determine --->     <!--- the height that preserves original aspect ratio --->     <cfif newHeight eq -1>       <cfset scaleY = scaleX>       <cfset newHeight = sourceHeight * scaleY>     </cfif>     <!--- Initialize destination image object --->     <cfset jbiDest.init(JavaCast("int", newWidth), JavaCast("int", newHeight), jbiSource .getType())>     <!--- Tell image-transformation object that we want to scale --->     <!--- (You can request other things, like rotation, etc) --->     <cfset jatTransformer.setToScale(scaleX, scaleY)>     <!--- Draw transformed version of image on destination object --->     <cfset jbiDest.getGraphics().drawRenderedImage(jbiSource, jatTransformer)>     <!--- Write the transformed version to disk --->     <cfset ImageIO.write(jbiDest, "jpeg", jfileOut)>   </cffunction> </cfcomponent> 

We won't go into depth about how this CFC works because we're assuming that you are familiar enough with Java to look up each class and method requested from the Java SDK. One thing to note is that we are calling the method getFileObject() that we created in the JavaFile.cfc. This CFC has one function, createResizedImage(), with four arguments: sourcePath, destPath, newWidth, and newHeight. These represent the path to the source file, the path to the destination file, the width of the thumbnail, and last the height of the thumbnail, respectively. The rest of the CFC uses various Java objects to get the files, transform the image, and write out the new file.

Now assume that after users upload their files to a directory, we want to give them the option of automatically creating thumbnails of every image in that directory. Also assume you want to delegate that task to a one of your assistant developers (hey, you're the advanced developerthat's why you are reading this book). Your assistant developer can now just look at the ImageManipulator.cfc and see what function must be called: createResizedImage, which has four arguments. They might then produce a simple CFML page like Listing 29.5.

Listing 29.5. createGallery.cfmCreating a Simple Photo Gallery.

[View full width]

 <!--- Location of images ---> <cfset GalleryFolder = ExpandPath("gallery")> <!--- Get list of images ---> <cfdirectory   action="list"   name="GetImages"   directory="#GalleryFolder#"   filter="*.jpg"> <!--- Loop over images ---> <cfloop query="GetImages">   <!--- Proposed location of thumbnail --->   <cfset ThumbPath = ExpandPath("gallery/thumbs/#Name#")>   <!--- If the thumbnail does not exist --->   <cfif not FileExists(ThumbPath)>     <cfoutput>Creating thumbnail for #Name#</cfoutput><br>     <cfflush>     <!--- Invoke our image-resizing function --->     <cfinvoke       component="ImageManipulator"       method="createResizedImage"       sourcePath="#GalleryFolder#/#Name#"       destPath="#ThumbPath#"       newWidth="100">   </cfif> </cfloop> <!--- Display thumbs, with links to full size images ---> <cfoutput query="GetImages">   <a href="gallery/#Name#"><img src="/books/2/449/1/html/2/gallery/thumbs/#Name#" width="100" height="75"  border="0" hspace="10" vspace="10"></a> </cfoutput> 

Before we look at this code you need to make sure you have a folder called gallery below the directory where you have put ImageManipultor.cfc and the createGallery.cfm like webroot\ JavaInteg\gallery. You also need a directory under gallery called thumbs like webroot\JavaInteg\ gallery\thumbs.

All this file does is loop through all the images in a directory called gallery, calls the ImageManipultor.cfc to create the thumbnails, and then shows the gallery that was created. You can put any images you want in the gallery folder, and when you run the script from the browser you'll see something like Figure 29.2. In the next section we are going to expand on the photo album application theme by using a java class that is not native to the Java SDK to add even more functionality to your applications.

Figure 29.2. An example gallery of thumbnails created by createGallery.cfm.


Using External Java Classes

You've seen how to use the standard classes included in the standard Java packages such as java.io.File. As stated earlier, you can call almost any Java object from ColdFusion MX 7, and sometimes you'll need to make use of classes other than those in the Java SDK. Perhaps you want to work with Java code someone else in your organization has created, or with something you have found that will solve a specific problem. To do this, you do need to follow additional steps before your can use external Java classes in your application:

1.

Install the class on your server. Typically, this means unpacking a .class or .jar file from a zip archive, or perhaps running some kind of installation program.

2.

Make sure the class can be found in the Class Path shown in the Java and JVM page of the ColdFusion Administrator. Basically, this means placing the .class or .jar file into a folder that's already listed in the Class Path, or adding the file's location to the Class Path. (Remember that the ColdFusion Application Server service must be restarted if you change the Class Path.) An alternative is to copy your .jar file to web_root/WEB-INF/lib, or your .class files to web_root/WEB-INF/classes, and ColdFusion will automatically be able to access your Java objects.

3.

Finally, use the class just as you would any other, using <CFOBJECT> or CreateObject().

A Practical Example

Suppose your manager has now decided that the photo album tool should be able to determine the height and width of images on-the-fly. This capability will come in handy if your application needs to display images that can't or shouldn't be hard-coded into <IMG> tags directly. For instance, if you are accepting images from your users via file uploads, you can use code similar to this example to find the dimensions of each image, or to disallow images that are too small or too large.

For Listing 29.6, you can use any image type but TIFF; and for our example we are using the image, box_cfmx7.gif, for the ColdFusion MX 7 application server box from Macromedia's site.

NOTE

Before Listing 29.6 will work, you must make the ImageInfo.class file (included with this chapter's listings) available in the Class Path as listed in the Java and JVM page of the ColdFusion Administrator. Either copy the file to a directory already listed in the Class Path or temporarily add the class's folder location to the Class Path. (You'll need to restart ColdFusion if you change the Class Path.) You may find the original Java class at http://www.geocities.com/marcoschmidt.geo/image-info.html.


Listing 29.6. JavaObjectImageInfo.cfmUsing an External Java Class
 <!---  Filename: JavaObjectImageInfo.cfm  Author: Nate Weiss (NMW)  Purpose: Shows how to use Marco Schmidt's ImageInfo class in CF pages  Depends On: The ImageInfo.class, which must be in ColdFusion's JVM class path  See http://www.geocities.com/marcoschmidt.geo for info & updates ---> <!--- This is the image we want to get information about ---> <cfset ImgSrc = "box_cfmx7.gif"> <!--- Use ExpandPath() to get the full filesystem path for the image file ---> <cfset ImgFile = ExpandPath(ImgSrc)> <!--- Create a FileInputStream to read the image file ---> <cfset inputstream = CreateObject("Java", "java.io.FileInputStream")> <cfset inputstream.init(ImgFile)> <!--- Load the ImageInfo class ---> <cfset imageinfo = CreateObject("Java", "ImageInfo")> <!--- Set the ImageInfo's input, which causes it to examine the image file ---> <cfset imageinfo.setInput(inputStream)> <html> <head><title>Using the ImageInfo Class</title></head> <body> <h2>Using the ImageInfo Class</h2> <!--- If the ImageInfo class was able to examine the image successfully ---> <cfif imageinfo.check()>  <cfoutput>  <!--- Display information about the image --->  image: #ImgSrc#<br>  type: #imageinfo.getFormatName()#<br>  width: #imageinfo.getWidth()#<br>  height: #imageinfo.getHeight()#<br><br>  <!--- Display the image itself --->  <img  src="/books/2/449/1/html/2/#ImgSrc#"  width="#imageinfo.getWidth()#"  height="#imageinfo.getHeight()#"><br>  </cfoutput> <!--- If the image doesn't exist ---> <cfelse>  <p>Sorry, could not obtain image info.<br> </cfif> 

First, a FileInputStream is created and initialized with the filename of the image to be examined. Next, an instance of ImageInfo is created, called imageinfo. Now the class's various methods can be called to get the desired effect: First, the setInput() method is used to tell the ImageInfo object which image it should examine. Next, the check() function is used to determine if the object was able to inspect the image. If so, the getWidth(), getHeight(), and getFormatName() functions are used to display the width, height, and image file format, respectively (Figure 29.3). As in previous examples, you could place this code inside a CFC, UDF, or custom tag to hide the interaction with Java and create a more-consistent coding environment. We will leave that as an exercise for you to try on your own.

Figure 29.3. Example of the image information returned by javaObject- ImageInfo.cfm.


If you would like more information about the methods used in this listing, consult the ImageInfo .html documentation file included with this chapter's listings.

About the ImageInfo Class

ImageInfo is an excellent, high-performance, pure Java class written by Marco Schmidt. It can quickly extract the file format, image size, number of bits per pixel, comments, and other information from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, and PSD images. It can even extract similar information from Macromedia Flash (.swf) files. ImageInfo is in the public domain and is available for free download from Marco's Web site. For your convenience, ImageInfo has been included with the listings for this book, but you are encouraged to check out Marco's site for any updates to the project: www.geocities.com/marcoschmidt.geo.

If you find the ImageInfo class interesting, you may also want to check out Marco's Java Imaging Utilities (JIU) library, which allows you to crop, rotate, apply filters to, and generally modify image files. The JUI library is available from www.geocities.com/marcoschmidt.geo or http://jiu.sourceforge.net.

Managing Method-Selection Problems

CFML is an extremely loosely typed language. Variables are not declared with a specific data type; the type (date, number, string, and so on) is intuited at run time based on context, and conversions between types are handled automatically. And the data types that ColdFusion does have are drawn with broad strokesthere is just one data type for numbers, for instance, rather than separate data types for integers, floating-point numbers, real numbers, and so on. This general policy of type leniency is a big part of why ColdFusion is so easy (and fun!) to use and learn. As a ColdFusion developer, data types just aren't on your mind very often.

In Java programming, however, data types and object types are absolutely critical, at the conceptual forefront of nearly any coding task. This is a big part of what gives Java its power and efficiency (at least potential efficiency, depending on how the JVM operates internally). This characteristic of Java also leads to a large number of overloaded methods. For instance, because integers and floating-point numbers are different, it's typical to find two different forms of a single method, one that accepts an int and one that accepts a double. In Java documentation, they might be listed like so:

 void fillWithGasoline(int gallons) void fillWithGasoline(double gallons) 

If you want to call this method from a ColdFusion page, you might use code like the following, where FORM.Gallons is a number of some kind:

 <cfset myNova.fillWithGasonline(FORM.Gallons)> 

However, ColdFusion will not know which of the two forms of the method to call, possibly resulting in an exception message like "method selection error" or something similar. In such a situation, you need to give ColdFusion a hint by using the special JavaCast() function. JavaCast() takes just two arguments, as listed in Table 29.3.

Table 29.3. JavaCast() Function Syntax

ATTRIBUTE

DESCRIPTION

type

One of the following strings, which indicates how you want the value passed to Java: int, long, double, or String.

value

The value that you want to pass to Java. The value can be a variable, string, number, or any other CFML expression.


So, to call the double version of the fillWithGasoline() method, you would use:

 <cfset myNova.fillWithGasonline(JavaCast("double", FORM.Gallons))> 

NOTE

You can also use JavaCast() inside of an init() call to avoid similar ambiguities when calling an object's constructor. The type information you provide with JavaCast() can help ColdFusion know which of several constructors to use.


TIP

There is another important thing to note about working with Java methods. It is extremely common for Java methods to return a null value. In previous versions of ColdFusion, including 6.1, this will cause a ColdFusion exception. ColdFusion MX 7 now has support for Java null values that are returned from Java methods, and ColdFusion MX 7 automatically converts the null value to an empty string (" "). Keep this in mind especially if you have worked with Java and ColdFusion prior to MX 7 and were accustomed to writing workaround code for this issue.


For some additional information on data type conversions, refer to the "Shared Variables and Data Types" and "Shared Variables and Multifaceted Values" sections later in this chapter.



Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net