You use the cfobject tag to create an instance of a Java object. You use other ColdFusion tags, such as cfset and cfoutput , or CFScript to invoke properties (attributes), and methods (operations) on the object.
Method arguments and return values can be any valid Java type; for example, simple arrays and objects. ColdFusion does the appropriate conversions when strings are passed as arguments, but not when they are received as return values. For more information on type conversion issues, see Java and ColdFusion data type conversions below.
The examples in this discussion assume that the name attribute in the cfobject tag specified the value obj, and that the object has a property called Property, and methods called Method1, Method2, and Method3.
Note: The cfdump tag displays the public methods and data of an object. |
Using basic object techniques
You can use ColdFusion to invoke Java objects and access object methods and properties.
Invoking objects
The cfobject tag makes Java objects available in ColdFusion. It can access any Java class that is available on the JVM classpath or in either of the following locations:
- In a Java archive (.jar) file in web_root/WEB-INF/lib
- In a class (.class) file in web_root/WEB-INF/classes
For example:
<cfobject type="Java" class="MyClass" name="myObj"> |
Although the cfobject tag loads the class, it does not create an instance object. Only static methods and fields are accessible immediately after the call to cfobject .
If you call a public non-static method on the object without first calling the init method, ColdFusion makes an implicit call to the default constructor.
To call an object constructor explicitly, use the special ColdFusion init method with the appropriate arguments after you use the cfobject tag; for example:
<cfset ret=myObj.init(arg1, arg2)> |
Note: The init method is not a method of the object, but a ColdFusion identifier that calls the new function on the class constructor. So, if a Java object has an init method, a name conflict exists and you cannot call the object init method. |
To have persistent access to an object, use the init function, because it returns a reference to an instance of the object, and cfobject does not.
An object created using cfobject or returned by other objects is implicitly released at the end of the ColdFusion page execution.
Using properties
Use the following coding syntax to access properties if the object does either of the following actions:
- Exposes the properties as public properties.
- Does not make the properties public, but is a JavaBean that provides public getter and setter methods of the form get_PropertyName_() and set_PropertyName_(value). For more information, see Calling JavaBean get and set methods below.
- To set a property: <cfset obj.property = "somevalue">
- To get a property: <cfset value = obj.property>
Note: ColdFusion does not require consistently capitalized property and method names. However, it is good programming practice to use the same case in ColdFusion as you do in Java to ensure consistency. |
Calling methods
Object methods usually take zero or more arguments. Some methods return values, while others might not. Use the following techniques to call methods:
If the method has no arguments, follow the method name with empty parentheses, as in the following cfsettag :
<cfset retVal = obj.Method1()>
If the method has one or more arguments, place the arguments in parentheses, separated by commas, as in the following example, which has one integer argument and one string argument:
<cfset retVal = obj.Method1(x, "a string literal")>
Note: When you invoke a Java method, the type of the data being used is important. For more information see Java and ColdFusion data type conversions below. |
Calling JavaBean get and set methods
ColdFusion can automatically invoke get_PropertyName_() and set_PropertyName_(value) methods if a Java class conforms to the JavaBeans pattern. As a result, you can set or get the property by referencing it directly, without having to explicitly invoke a method.
For example, if the myFishTank class is a JavaBean, the following code returns the results of calling the getTotalFish() method on the myFish object:
There are currently #myFish.TotalFish# fish in the tank. |
The following example adds one guppy to a myFish object by implicitly calling the setGuppyCount(int number) method:
<cfset myFish.GuppyCount = myFish.GuppyCount + 1> |
Note: You can use the direct reference method to get or set values in some classes that have getProperty and setProperty methods but do not conform fully to the JavaBean pattern. However, you cannot use this technique for all classes that have getProperty and setProperty methods. For example, you cannot directly reference any of the following standard Java classes, or classes derived from them: Date, Boolean, Short, Integer, Long, Float, Double, Char, Byte, String, List, Array. |
Calling nested objects
ColdFusion supports nested (scoped) object calls. For example, if an object method returns another object and you invoke a property or method on that object, you can use the following syntax:
<cfset prop = myObj.X.Property>. |
Similarly, you can use code such as the following CFScript line:
GetPageContext().include("hello.jsp?name=Bobby");
In this code, the ColdFusion GetPageContext function returns a Java PageContext object, and the line invokes the include method of the PageContext object.
Creating and using a simple Java class
Java is a strongly typed language, unlike ColdFusion, which does not enforce data types. As a result, some subtle considerations exist when calling Java methods.
The Employee class
The Employee class has four data members: FirstName and LastName are public, and Salary and JobGrade are private. The Employee class has three overloaded constructors and an overloaded SetJobGrade method. Save the following Java source code in the file Employee.java, compile it, and place the resulting Employee.class file in a directory that is specified in the classpath:
|
A CFML page that uses the Employee class
Save the following text as JEmployee.cfm:
<body> |
When you view the page in your browser, you get the following output: Employee name is john doe
Reviewing the code
The following table describes the CFML code and its function:
Code |
Description |
|
---|---|---|
|
Loads the Employee Java class and gives it an object name of emp . |
|
|
Does not call a constructor. ColdFusion calls the default constructor when it first uses the class; in this case, when it processes the next line. |
|
|
Sets the public fields in the emp object to your values. |
|
|
Gets the field values back from emp object. |
|
|
Displays the retrieved values. |
Java considerations
The following points are important when you write a ColdFusion page that uses a Java class object:
- The Java class name is case sensitive. Ensure that the Java code and the CFML code use Employee as the class name.
- Although Java method and field names are case sensitive, ColdFusion variables are not case sensitive, and ColdFusion does any necessary case conversions. As a result, the sample code works even though the CFML uses emp.firstname and emp.lastname; the Java source code uses FirstName and LastName for these fields.
- If you do not call the constructor (or, as in this example, comment it out), ColdFusion automatically runs the default constructor when it first uses the class.
Using an alternate constructor
The following ColdFusion page explicitly calls one of the alternate constructors for the Employee object:
<body> |
In this example, the constructor takes four arguments: the first two are strings, the third is a float, and the fourth is an integer.
Java and ColdFusion data type conversions
ColdFusion does not use explicit types for variables, while Java is strongly typed. However, ColdFusion data does use underlying Java types to represent data.
Under most situations, when the method names are not ambiguous, ColdFusion can determine the data types that a Java object requires, and often it can convert ColdFusion data to the required types. For example, ColdFusion text strings are implicitly converted to the Java String type. Similarly, if a Java object contains a doIt method that expects a parameter of type int, and CFML is issuing a doIt call with a CFML variable x that contains an integer value, ColdFusion converts the variable x to Java int type. However, ambiguous situations can result from Java method overloading, where a class has multiple implementations of the same method that differ only in their parameter types.
Default data type conversion
Whenever possible, ColdFusion automatically matches Java types to ColdFusion types.
The following table lists how ColdFusion converts ColdFusion data values to Java data types when passing arguments. The left column represents the underlying ColdFusion representation of its data. The right column indicates the Java data types into which ColdFusion can automatically convert the data:
CFML |
Java |
---|---|
Integer |
short, int, long (short and int can result in a loss of precision). |
Real number |
float double (float can result in a loss of precision. |
Boolean |
boolean |
Date-time |
java.util.Date |
String, including lists |
Stringshort, int, long, float, double, java.util.Date, when a CFML string represents a number or date.boolean, for strings with the value Yes, No, True, and False (case-insensitive). |
Array |
java.util.Vector (ColdFusion Arrays are internally represented using an instance of a java.util.Vector object.)ColdFusion can also map a CFML array to any of the following when the CFML array contains consistent data of a type that can be converted to the data type of the Java arr: byte[], char[], boolean[], int[], long[], float[], double[], String[], or Object[]. When a CFML array contains data of different of types, the conversion to a simple array type could fail. |
Structure |
java.util.Map |
Query object |
util.map and vectors together. If you have dynamic column names, you can retrieve it as queryname[column name][current row]. |
XML document object |
Not supported. |
ColdFusion component |
Not applicable. |
The following table lists how ColdFusion converts data returned by Java methods to ColdFusion data types:
Java |
CFML |
---|---|
boolean/Boolean |
Boolean |
byte/Byte |
String |
char/Char |
String |
short/Short |
Integer |
int/Integer |
Integer |
long/Long |
Integer |
float/Float |
Real Number |
double/Double |
Real Number |
String |
String |
java.util.Date |
Date-time |
java.util.List |
Comma-delimited list |
byte[] |
Array |
char[] |
Array |
boolean[] |
Array |
String[] |
Array |
java.util.Vector |
Array |
java.util.Map |
Structure |
Resolving ambiguous data types with the JavaCast function
You can overload Java methods so a class can have several identically named methods. At runtime, the JVM resolves the specific method to use based on the parameters passed in the call and their types.
In the section The Employee class, the Employee class has two implementations for the SetJobGrade method. One method takes a string variable, the other an integer. If you write code such as the following, which implementation to use is ambiguous:
<cfset emp.SetJobGrade("1")> |
The "1" could be interpreted as a string or as a number, so no way exists to know which method implementation to use. When ColdFusion encounters such an ambiguity, it throws a user exception.
The ColdFusion JavaCast function helps you resolve such issues by specifying the Java type of a variable, as in the following line:
<cfset emp.SetJobGrade(JavaCast("int", "1"))> |
The JavaCast function takes two parameters: a string representing the Java data type, and the variable whose type you are setting. You can specify the following Java data types: boolean, int, long, float, double, and String.
For more information about the JavaCast function, see the CFML Reference.
Handling Java exceptions
You handle Java exceptions just as you handle standard ColdFusion exceptions, with the cftry and cfcatch tags. You specify the name of the exception class in the cfcatch tag that handles the exception. For example, if a Java object throws an exception named myException, you specify myException in the cfcatch tag.
Note: To catch any exception generated by a Java object, specify java.lang.Exception for the cfcatch type attribute. To catch any Throwable errors, specify java.lang.Throwable in the cfcatch tag type attribute. |
For more information on exception handling in ColdFusion, see Handling Errors.
Example: exception-throwing class
The following Java code defines the testException class that throws a sample exception. It also defines a myException class that extends the Java built-in Exception class and includes a method for getting an error message.
The myException class has the following code. It throws an exception with a message that is passed to it, or if no argument is passed, it throws a canned exception.
//class myException |
The testException class contains one method, doException, which throws a myException error with an error message, as follows:
public testException () |
Example: CFML Java exception handling code
The following CFML code calls the testException class doException method. The cfcatch block handles the resulting exception.
<cftry> |
Examples: using Java with CFML
The following examples show several examples of using Java objects in CFML. They include examples of using a custom Java class, a standard Java API class in a user-defined function, a JavaBean, and an Enterprise JavaBean (EJB).
Using a Java API in a UDF
The following example of a user-defined function (UDF) is functionally identical to the GetHostAddress function from the NetLib library of UDFs from the Common Function Library Project, www.cflib.org. It uses the InetAddress class from the standard Java 2 java.net package to get the Internet address of a specified host:
function GetHostAddress(host) { |
Using an EJB
ColdFusion can use EJBs that JRun 4.0 servers provide. The JRun server jrun.jar file must have the same version as the jrun.jar file in ColdFusion.
To call an EJB, you use cfobject to create and call the appropriate objects. Before you use an EJB, do the following:
- Have a properly deployed EJB running on a J2EE server. The bean must be registered with the JNDI server.
- Have the following information:
- Name of the EJB server
- Port number of the JNDI naming service on the EJB server
- Name of the EJB, as registered with the naming service
- Install the EJB home and component interface compiled classes on your ColdFusion web server, either as class files in the web_root/WEB-INF/classes directory or packaged in a JAR file the web_root/WEB-INF/lib directory.
Note: To use an EJB served by a JRUN server, your ColdFusion installation and the JRun server that hosts the EJB must have the same version of the jrun.jar file (located in cf_root\runtime\lib directory in ColdFusion). |
Although the specific steps for using an EJB depend on the EJB server and on the EJB itself, they generally correspond to the following order.
- Use the cfobject tag to create an object of the JNDI naming context class ( javax .naming.Context). You use fields from this class to define the information that you use to locate the EJB. Because you only use fields, you do not initialize the object.
- Use the cfobject tag to create a java.util.Properties class object to contain the context object properties.
- Call the init method to initialize the Properties object.
- Set the Properties object to contain the properties that are required to create an initial JNDI naming context. These properties include the INITIAL_CONTEXT_FACTORY and PROVIDER_URL properties. You could also need to provide SECURITY_PRINCIPAL and SECURITY_CREDENTIALS values required for secure access to the naming context. For more information on these properties, see the JNDI documentation.
- Use the cfobject tag to create the JNDI InitialContext ( javax .naming. InitialContext) object.
- Call the init method for the InitialContext object with the Properties object values to initialize the object.
- Call the lookup method of the InitialContextext object to get a reference to the home interface for the bean that you want. Specify the JNDI name of the bean as the lookup argument.
- Call the create method of the bean home object to create an instance of the bean. If you are using Entity beans, you typically use a finder method instead. A finder method locates one or more existing entity beans.
- Now you can use the bean methods as required by your application.
- When finished, call the close method of the context object to close the object.
The following code shows this process using a simple Java Entity bean on a JRun 4.0 server. It calls the getMessage method of the bean to obtain a message.
<head> |
Using a custom Java class
The following code provides a more complex custom class than in the example Creating and using a simple Java class. The Example class manipulates integer, float, array, Boolean, and Example object types.
The Example class
The following Java code defines the Example class. The Java class Example has one public integer member, mPublicInt. Its constructor initializes mPublicInt to 0 or an integer argument. The class has the following public methods:
Method |
Description |
---|---|
ReverseString |
Reverses the order of a string. |
ReverseStringArray |
Reverses the order of elements in an array of strings. |
Add |
Overloaded: Adds and returns two integers or floats or adds the mPublicInt members of two Example class objects and returns an Example class object. |
SumArray |
Returns the sum of the elements in an integer array. |
SumObjArray |
Adds the values of the mPublicInt members of an array of Example class objects and returns an Example class object. |
ReverseArray |
Reverses the order of an array of integers. |
Flip |
Switches a Boolean value. |
public int mPublicInt; |
The useExample ColdFusion page
The following useExample.cfm page uses the Example class to manipulate numbers, strings, Booleans, and Example objects. The CFML JavaCast function ensures that CFML variables convert into the appropriate Java data types.
<head>
|