Section 10.2. Using

   

10.2 Using <cfobject>

Any compiled Java class can be called from within a regular ColdFusion template using the <cfobject> tag, as long as it is available to the class path as specified in the ColdFusion Administrator settings.

There are many ways to incorporate Java into your ColdFusion Web applications. How you employ the different options available to you will depend on the scope and nature of the project and the personnel involved. The third part of this book is devoted to writing Web applications exclusively in Java with JavaServer Pages, servlets, and Enterprise JavaBeans. Using <cfobject> will likely mean that you have a Web app written in ColdFusion that needs to perform one or two complex functions that might be better handled in Java, or it may mean that you need to interoperate with some other software installed on the server, and a Java object is the way to do it.

This tag is used to invoke not only Java objects, but also COM objects, CORBA objects, and Web services. In this chapter we will only discuss its use with Java objects. For a look at the attributes of the <cfobject> tag, see Table 10.1.

Note

There is an alternative to using the <cfobject> tag. To invoke an object from within a <cfscript> block, you use the CreateObject() statement. We will look at examples using both syntaxes.


Table 10.1. <cfobject> Tag Attributes

Attribute

Description

type

For use with Java objects, specify type="Java" . Other values are COM and CORBA.

action

Create: specifies the creations of a Java or BEA WebLogic Environment object.

class

The Java class to use.

name

String name for the instantiated component.

Here is the flow of execution when invoking Java objects in a ColdFusion template: First, call <cfobject> or CreateObject() to create an instance of the object. Note that calling an object using the <cfobject> tag and the function version CreateObject() does not call the constructor for that object. In order to call the constructor, you need to use ColdFusion's init() method. This method replicates the functionality of the Java keyword new . ColdFusion will make an implicit call to the default constructor if you call a public method before calling init() .

Once you have created an object instance, you can refer to its fields and methods using <cfset> , and you can then output their results using <cfoutput> . At the end of template execution, the object is implicitly released.

10.2.1 Invoking and Instantiating a Java Object

Here is the syntax for creating an object using the tag version:

 <cfobject type="Java" action="create" class="MyClass"  name="myObj"> 

Here is the syntax for creating an object using <cfscript> :

 <cfscript>       myObj = CreateObject("Java", "MyClass"); </cfscript> 

Invoking the object in this way only loads the object's class into memory ”it does not create an instance of the object. So you now need to create an instance of the object, and you have two ways you can do it.

The first way to do this is to simply call any of the object's public fields or methods. Doing so automatically forces a call to the default constructor. Your other option, of course, is to call one of the object's constructors.

You can call a constructor defined within the class with init() , which is a ColdFusion function for this purpose. It means that you cannot have an init() method defined in your Java class. Calling init() when you have an identically named method in your Java class will cause an exception to be thrown.

Note

You can call Enterprise JavaBeans using the <cfobject> tag. However, this practice is generally not recommended, and it requires extra work with your application servers.


10.2.2 Setting and Retrieving Field Values

To set the value of a field in a Java object you have invoked, use the <cfset> tag:

 <cfset myObj.someField = "somevalue"> 

To retrieve the value of a field and assign a ColdFusion variable to its value, you leave out the quote marks around the field name:

 <cfset var = myObj.someField> 

10.2.3 Calling Object Methods

You similarly use the <cfset> tag to call the methods of a Java object:

 <cfset someValue = myObj.getItem()> 

10.2.4 Using JavaCast()

The JavaCast() function is used for scalar and string arguments for use with overloaded constructors. This function converts the data type of a ColdFusion variable to pass it as an argument to an overloaded method of a Java object.

You use the JavaCast() function after you have created an object with the <cfobject> tag, but before you call one of its methods. Use JavaCast() only for overloaded methods that accept arguments of more than one data type. Its purpose is to determine which constructor you mean to call when sending a different data type is the only distinguishing factor between constructors.

Note

A quick reminder if you're having trouble keeping the terminology straight: Overloading a constructor or method means creating multiple methods or constructors with the same name but different signatures.


The JavaCast() function converts a ColdFusion variable into one of the following types:

  • boolean

  • double

  • int

  • long

  • String

The JavaCast() function takes two parameters: type , representing the type into which you want to cast the variable, and var , representing the ColdFusion variable to be cast. It has the following syntax:

 JavaCast(type, var) // both required 

ColdFusion, as you know, is a weakly typed language. That makes it very easy to start using ColdFusion, but a little tricky when integrating with strongly typed languages such as Java. You may not always get entirely predictable results when using this function.

Here is a simple example using the <cfobject> tag and the JavaCast() function. First, we'll define a quick Java class, and then we'll write a Cold-Fusion template that we can use to instantiate it.

10.2.5 CFObjTest.java

 /* used with CFOBjectTest.cfm   * to demonstrate working with Java  * classes from inside CF templates  */ public class CFObjTest {     public String message;     //default constructor     public CFObjTest() {         message = "No message specified.";     }         // set the message     public void setMessage(String s) {         message = s;     }     // retrieve message     public String getMessage() {         return message;   } } 

10.2.6 CFObjectTest.cfm

 <!---  File: chp10/ObjTest.cfm Purpose: demonstrate <cfobject> Call an overloaded constructor Send a message into the object and have it print the message the number of times specified. ---> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>&lt;cfobject test&gt;</title> </head> <body> Loading object... <cfobject type="JAVA" action="create" name="ATest" class="CFObjTest"> <br> <br> <!---set message to be printed---> <cfset setIt=ATest.setMessage("Well hello, Mr. Fancy Pants.")> <!--- retrieve the message from the object---> <cfset msg = ATest.getMessage()> <cfoutput> Here is your message: <br> <b>#msg#</b> </cfoutput> </body> </html> 

Note

If you need to restart ColdFusion manually, you can do so by executing the program at C:\CFusionMX\runtime\bin . This will bring up the JRun launcher, and you can start the server from there.


10.2.7 Running the Test

There are a few things you may need to do to run this test. First, add a directory that we can run ColdFusion tests out of, and set the server's class path to find that directory. I will make mine C:\CFusionMX\ wwwroot \chp10 , (the comma will automatically be added for you).

Then we will put the ColdFusion template CFObjTest.cfm in this directory on the server, and we'll put the ObjTest.java file in the same directory. Compile the Java class. Call the following URL in your browser: http://localhost:8500/chp10/CFObjTest.cfm .

Here is your output to the browser:

Loading object

Here is your message:

Well hello, Mr. Fancy Pants.

It's a lot of work, but getting such an inspiring message back is worth it.

Let's look at another quick example that uses the JavaCast() function. I would not recommend calling Java objects from ColdFusion in this way with much intensity or frequency. If you think you'll need to do that, do your work in JSPs or servlets that have containers made specially to run them. Actually, ColdFusion MX Enterprise and Development versions will execute JSPs directly, which is more stable.

10.2.8 Testing the JavaCast() Function

[View full width]
 
[View full width]
<!--- File: JavaCastTest.cfm\ Purpose: demonstrate use of JavaCast function ---> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Test 2</title> </head> <body> <!---load class---> <cfobject type="JAVA" action="create" name="ATest" class="JavaCastTest"> <!---call object's overloaded method, using JavaCast to determine which method will be graphics/ccc.gif called---> <cfset msg = ATest.getVar(JavaCast("String", 007))> <!----output the result---> <cfoutput>#msg#</cfoutput> </body> </html>

This file simply loads the object of class JavaCastTest , and it then uses the JavaCast() function to determine which method it will call. Below we create the simple class file it uses. This test shows the full extent and purpose of this function ”it settles disputes in translation from a weakly typed language to a strongly typed language.

10.2.9 JavaCastTest.java

 public class JavaCastTest { public String getVar(String s) {   message = "I am a String";   return message;   } // overloaded public String getVar(int i) { message = "I am an int";   return message;   } } 

Compile and run this just as the previous example. Here is your output to the browser:

 I am a String 

There used to be more uses for this tag and function, as Java support was not as strong, and other functionality that could be exposed to ColdFusion as objects now have been incorporated into ColdFusion MX. For instance, parsing XML from within ColdFusion previously required programs such as Microsoft's XML parser. You could use the <cfobject> tag to access XML nodes it parsed and traverse the tree. Now, you can use the <cfxml> tag. But that is another subject.

10.2.10 An Advanced <cfobject> Example

Here we look at a code listing that addresses a common problem in ColdFusion. We will read in the contents of a file line by line. This task is generally accomplished using <cffile> . However, the <cffile> tag reads a file into memory all at once. Your environment may require a more judicious use of memory, particularly if you are reading in a large file containing a lot of data.

The typical way of reading in a file line by line would be to create a FileReader object, pass that object to a BufferedReader , and call its readLine() method to read in the file. This poses a subtle and interesting dilemma.

When the BufferedReader.readLine() method reaches the end of a line, it returns a null value. So when using this method from within ColdFusion, we face a problem: ColdFusion does not have null s like Java does. ColdFusion instead will return an empty string ”which means that we cannot determine the difference between a blank line within the file and the end of the dataset (the end of the file).

This example therefore has the added benefit of demonstrating further use of subclassing. In order to work around this, we need to subclass Java's Buffered-Reader . This file will differentiate between a blank line and the end of the file.

The Java source code and ColdFusion template for this example were written by Daryl Banttari, senior consultant at Macromedia, and they are used by permission.

10.2.11 CFBufferedReader.java

 //CFBufferedReader  // Purpose: //   Since ColdFusion automatically turns "null" Strings into //   empty strings, //   it is necessary to extend BufferedReader so that we can //   detect //   the null string returned from readLine(). //// Use: //   CFBufferedReader works exactly like //   java.io.BufferedReader, //   but adds an isEOF() method to indicate whether the last //   call //   to readLine detected the end of the file. //// Author: //   Daryl Banttari (Macromedia) //// Copyright: (c)2001 Macromedia import java.io.*; //   Define this class as a subclass of java.io.BufferedReader public class CFBufferedReader extends java.io.BufferedReader { // variable to hold the EOF status of the last read // default to false; we'll assume you're not at eof if // we haven't read anything yet      private boolean eof = false;      // our class constructors will simply pass the arguments      // through to our superclass, BufferedReader:      public CFBufferedReader(Reader in, int sz) {           // "super" is an alias to the superclass.           // calling super() in this fashion actually        // invokes the superclass' constructor method.                            super(in, sz);      }      public CFBufferedReader(Reader in) {           super(in);      }      // here we extend the readLine method:    public String readLine() throws java.io.IOException {                String curLine;                   // call the "real" readLine() method from the superclass                   curLine = super.readLine();                   // now set eof to "is curline null?"           // note that there are two equals signs between "curLine" and "null"           eof = (curLine == null);                   // return curline to the caller "as is"                   return curLine;            }      public boolean isEOF() {              // simply return the current value if the eof variable                   return eof;        } } 

Now compile CFBufferedReader.java in the Chapter 10 directory. We will call it using <cfobject> and the following ColdFusion template: JavaFile-Test.cfm . This file will read itself in and replace < characters with &lt; .

10.2.12 JavaFileTest.cfm

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html> <head> <!---Author: Daryl Banttari--->         <title>Java File Example</title> </head> <body> <!--- get our filename from the CGI environment ---> <cfset fn = cgi.cf_template_path> <!--- create a Java FileReader object to read this file ---> <!--- note that java.io.FileReader is a native Java class.---> <cfobject type="Java" class="java.io.FileReader" name="fr" action="create"> <!--- when calling Java from CF, the constructor is called "init()" ---> <cfset fr.init(fn)> <!--- now pass the FileReader object to our extended BufferedReader ---> <cfobject type="Java" class="CFBufferedReader" name="reader" action="create"> <cfset reader.init(fr)> <!--- read the first line from the file ---> <cfset curLine=reader.readLine()> <!--- now loop until we reach the end of the file ---> <cfloop condition="not #reader.isEOF()#">         <!--- display the current line --->         <cfoutput>#replace(curLine,"<","&lt;","ALL")#<br>         </cfoutput>         <!--- flush the output buffer (cf5 only) --->         <cfflush>         <!--- each call to readLine( ) reads the /next/ line,           until the end of the file is reached, at which point       isEOF( ) starts returning "true" --->         <cfset curLine=reader.readLine()> </cfloop> </body> </html> 

Now call JavaFileTest.cfm like this: http://localhost:8500/chp10/JavaFileTest.cfm . The file will call the object, read in the file, replace the characters as mentioned, and output the file to the browser. If you had a Web site on which you wanted to display ColdFusion source code without it being processed by the CFAS, you could return it to the browser for readers using these files.


   
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

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