Using Java objects

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:

  1. If the method has no arguments, follow the method name with empty parentheses, as in the following  cfsettag :

    <cfset retVal = obj.Method1()>

     

  2. 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.
</cfoutput>

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:


public String FirstName;
public String LastName;
private float Salary;
private int JobGrade;

public Employee() {
FirstName ="";
LastName ="";
Salary = 0.0f;
JobGrade = 0;
}

public Employee(String First, String Last) {
FirstName = First;
LastName = Last;
Salary = 0.0f;
JobGrade = 0;
}

public Employee(String First, String Last, float salary, int grade) {
FirstName = First;
LastName = Last;
Salary = salary;
JobGrade = grade;
}

public void SetSalary(float Dollars) {
Salary = Dollars;
}

public float GetSalary() {
return Salary;
}

public void SetJobGrade(int grade) {
JobGrade = grade;
}

public void SetJobGrade(String Grade) {
if (Grade.equals("CEO")) {
JobGrade = 3;
}
else if (Grade.equals("MANAGER")) {
JobGrade = 2;
}
else if (Grade.equals("DEVELOPER")) {
JobGrade = 1;
}
}

public int GetJobGrade() {
return JobGrade;
}

}

A CFML page that uses the Employee class

Save the following text as JEmployee.cfm:

<body>
<cfobject action="create" type="java" class="Employee" name="emp">
<!--- <cfset emp.init()> --->
<cfset emp.firstname="john">
<cfset emp.lastname="doe">
<cfset firstname=emp.firstname>
<cfset lastname=emp.lastname>
</body>

<cfoutput>
Employee name is #firstname# #lastname#
</cfoutput>
</html>

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

 

<cfobject action=create type=java class=Employee name=emp>

 

Loads the Employee Java class and gives it an object name of emp .

 

<!--- <cfset emp.init()> --->

 

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.

 

<cfset emp.lastname="doe">

 

Sets the public fields in the emp object to your values.

 

<cfset lastname=emp.lastname>

 

Gets the field values back from emp object.

 

Employee name is #firstname# #lastname#
</cfoutput>

 

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>

<cfobject action="create" type="java" class="Employee" name="emp">
<cfset emp.init("John", "Doe", 100000.00, 10)>
<cfset firstname=emp.firstname>
<cfset lastname=emp.lastname>
<cfset salary=emp.GetSalary()>
<cfset grade=emp.GetJobGrade()>

<cfoutput>
Employee name is #firstname# #lastname#<br>
Employee salary #DollarFormat(Salary)#<br>
Employee Job Grade #grade#
</cfoutput>

</body>
</html>

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
public class myException extends Exception
{
public myException(String msg) {
super(msg);
}
public myException() {
super("Error Message from myException");
}
}

The testException class contains one method, doException, which throws a myException error with an error message, as follows:

public testException ()
{
}
public void doException() throws myException {
throw new myException("Throwing an exception from testException class");
}
}

Example: CFML Java exception handling code

The following CFML code calls the testException class doException method. The cfcatch block handles the resulting exception.

<cftry>
<cfset Obj.doException() >
<cfcatch type="myException">
<cfoutput>
<br>The exception message is: #cfcatch.Message#<br>
</cfoutput>
</cfcatch>
</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) {
// Define the function local variables.
var iaddrClass="";
var address="";
// Initialize the Java class.
iaddrClass=CreateObject("java", "java.net.InetAddress");
// Get the address object.
address=iaddrClass.getByName(host);
// Return the address
return address.getHostAddress();
}
</cfscript>
<cfoutput>#gethostaddress("adobe.com")#</cfoutput>

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:

  1. Have a properly deployed EJB running on a J2EE server. The bean must be registered with the JNDI server.
  2. 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
  3. 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.

  1. 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.
  2. Use the  cfobject  tag to create a java.util.Properties class object to contain the context object properties.
  3. Call the init method to initialize the Properties object.
  4. 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.
  5. Use the  cfobject  tag to create the JNDI InitialContext ( javax .naming. InitialContext) object.
  6. Call the init method for the InitialContext object with the Properties object values to initialize the object.
  7. 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.
  8. 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.
  9. Now you can use the bean methods as required by your application.
  10. 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>
<title>cfobject Test</title>
</head>

<body>
<H1>cfobject Test</H1>
<!--- Create the Context object to get at the static fields. --->
<CFOBJECT
action=create
name=ctx
type="JAVA"
class="javax.naming.Context">

<!--- Create the Properties object and call an explicit constructor--->
<CFOBJECT
action=create
name=prop
type="JAVA"
class="java.util.Properties">

<!--- Call the init method (provided by cfobject)
to invoke the Properties object constructor. --->
<cfset prop.init()>

<!--- Specify the properties These are required for a remote server only --->
<cfset prop.put(ctx.INITIAL_CONTEXT_FACTORY, "jrun.naming.JRunContextFactory")>
<cfset prop.put(ctx.PROVIDER_URL, "localhost:2908")>
<!--- <cfset prop.put(ctx.SECURITY_PRINCIPAL, "admin")>
<cfset prop.put(ctx.SECURITY_CREDENTIALS, "admin")>
--->
<!--- Create the InitialContext --->
<CFOBJECT
action=create
name=initContext
type="JAVA"
class="javax.naming.InitialContext">

<!--- Call the init method (provided through cfobject)
to pass the properties to the InitialContext constructor. --->
<cfset initContext.init(prop)>

<!--- Get reference to home object. --->
<cfset home = initContext.lookup("SimpleBean")>

<!--- Create new instance of entity bean.
(hard-wired account number). Alternatively,
you would use a find method to locate an existing entity bean. --->
<cfset mySimple = home.create()>

<!--- Call a method in the entity bean. --->
<cfset myMessage = mySimple.getMessage()>

<cfoutput>
#myMessage#<br>
</cfoutput>

<!--- Close the context. --->
<cfset initContext.close()>

</body>
</html>

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;

public Example() {
mPublicInt = 0;
}

public Example(int IntVal) {
mPublicInt = IntVal;
}

public String ReverseString(String s) {
StringBuffer buffer = new StringBuffer(s);
return new String(buffer.reverse());
}

public String[] ReverseStringArray(String [] arr) {
String[] ret = new String[arr.length];
for (int i=0; i < arr.length; i++) {
ret[arr.length-i-1]=arr[i];
}
return ret;
}

public int Add(int a, int b) {
return (a+b);
}

public float Add(float a, float b) {
return (a+b);
}

public Example Add(Example a, Example b) {
return new Example(a.mPublicInt + b.mPublicInt);
}

static public int SumArray(int[] arr) {
int sum=0;
for (int i=0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}

static public Example SumObjArray(Example[] arr) {
Example sum= new Example();
for (int i=0; i < arr.length; i++) {
sum.mPublicInt += arr[i].mPublicInt;
}
return sum;
}

static public int[] ReverseArray(int[] arr) {
int[] ret = new int[arr.length];
for (int i=0; i < arr.length; i++) {
ret[arr.length-i-1]=arr[i];
}
return ret;
}

static public boolean Flip(boolean val) {
System.out.println("calling flipboolean");
return val?false:true;
}
}

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>
<title>CFOBJECT and Java Example</title>
</head>
<body>

<!--- Create a reference to an Example object --->
<cfobject action=create type=java class=Example name=obj>
<!--- Create the object and initialize its public member to 5 --->
<cfset x=obj.init(JavaCast("int",5))>

<!--- Create an array and populate it with string values,
then use the Java object to reverse them. --->
<cfset myarray=ArrayNew(1)>
<cfset myarray[1]="First">
<cfset myarray[2]="Second">
<cfset myarray[3]="Third">
<cfset ra=obj.ReverseStringArray(myarray)>

<!--- Display the results --->
<cfoutput>
<br>
original array element 1: #myarray[1]#<br>
original array element 2: #myarray[2]#<br>
original array element 3: #myarray[3]#<br>
after reverseelement 1: #ra[1]#<br>
after reverseelement 2: #ra[2]#<br>
after reverseelement 3: #ra[3]#<br>
<br>
</cfoutput>


<!--- Use the Java object to flip a Boolean value, reverse a string,
add two integers, and add two float numbers --->
<cfset c=obj.Flip(true)>
<cfset StringVal=obj.ReverseString("This is a test")>
<cfset IntVal=obj.Add(JavaCast("int",20),JavaCast("int",30))>
<cfset FloatVal=obj.Add(JavaCast("float",2.56),JavaCast("float",3.51))>

<!--- Display the results --->
<cfoutput>
<br>
StringVal: #StringVal#<br>
IntVal: #IntVal#<br>
FloatVal: #FloatVal#<br>
<br>
</cfoutput>

<!--- Create a two-element array, sum its values,
and reverse its elements --->
<cfset intarray=ArrayNew(1)>
<cfset intarray[1]=1>
<cfset intarray[2]=2>
<cfset IntVal=obj.sumarray(intarray)>
<cfset reversedarray=obj.ReverseArray(intarray)>

<!--- Display the results --->
<cfoutput>
<br>
IntVal1 :#IntVal#<br>
array1: #reversedarray[1]#<br>
array2: #reversedarray[2]#<br>
<br>
</cfoutput><br>

<!--- Create a ColdFusion array containing two Example objects.
Use the SumObjArray method to add the objects in the array
Get the public member of the resulting object--->
<cfset oa=ArrayNew(1)>
<cfobject action=create type=java class=Example name=obj1>
<cfset VOID=obj1.init(JavaCast("int",5))>
<cfobject action=create type=java class=Example name=obj2>
<cfset VOID=obj2.init(JavaCast("int",10))>
<cfset oa[1] = obj1>
<cfset oa[2] = obj2>
<cfset result = obj.SumObjArray(oa)>
<cfset intval = result.mPublicInt>

<!--- Display the results --->
<cfoutput>
<br>
intval1: #intval#<br>
<br>
</cfoutput><br>
</body>
</html>

 

 Adobe

Get help faster and easier

New user?