ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
941
Under most situations, when the method names are not ambiguous, ColdFusion can determine the data types that
are required by a Java object, 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.
The following sections describe how ColdFusion handles the unambiguous situations, and how it provides you with
the tools to handle ambiguous ones.
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:
The following table lists how ColdFusion converts data returned by Java methods to ColdFusion data types:
CFML Java
Integer short, int, long (short and int might result in a loss of precision).
Real number float double (float might result in a loss of precision.
Boolean boolean
Date-time java.util.Date
String, including lists String
short, 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 Java array’s data type: byte[], char[], boolean[], int[], long[],
float[], double[], String[], or Object[]. When a CFML array contains data of different of types, the conver-
sion to a simple array type might fail.
Structure java.util.Map
Query object java.util.Map
XML document object Not supported.
ColdFusion component Not applicable.
Java CFML
boolean/Boolean Boolean
byte/Byte String
char/Char String
short/Short Integer
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
942
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” on page 938, 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 there is no way 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.
The following sections show an example of throwing and handling a Java exception.
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
Java CFML
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
943
For more information on exception handling in ColdFusion, see “Handling Errors” on page 246.
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 class testException {
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.
<cfobject action=create type=java class=testException name=Obj>
<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 sections 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:
<cfscript>
function GetHostAddress(host) {
// Define the function local variables.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
944
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 are served by JRun 4.0 servers. 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 type="Java" to create and call the appropriate objects. Before you can use an EJB
you must 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 corre-
spond to the following order.
Use an EJB
1
Use the cfobject tag to create an object of the JNDI naming context class (javax.naming.Context). You will 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 that will 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 include the INITIAL_CONTEXT_FACTORY and PROVIDER_URL properties. You might 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 InitialContextext object’s lookup method 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’s home object to create a new 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.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
945
9 Now you can use the bean’s methods as required by your application.
10 When finished, call the context object’s close method 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 bean’s
getMessage method to obtain a message.
<html>
<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>
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
946
#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” on page 938. 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:
public class Example {
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;
}
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.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
947
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.
<html>
<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">
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
948
<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)>
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
949
<cfset intval = result.mPublicInt>
<! Display the results >
<cfoutput>
<br>
intval1: #intval#<br>
<br>
</cfoutput><br>
</body>
</html>
950
Chapter 50: Using Microsoft .NET
Assemblies
You can use ColdFusion to call local or remote Microsoft .NET assembly class methods and access assembly fields.
This topic describes how to configure and run the ColdFusion .NET extension software and how to access and use
.NET classes in your ColdFusion code. For information about .NET technology or how to develop .NET applica-
tions, see Microsoft .NET documentation.
Contents
About ColdFusion and .NET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 950
Accessing .NET assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 953
Using .NET classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 957
.NET Interoperability Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 965
Example: Using a custom class to access Microsoft Word . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 966
Advanced tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 968
About ColdFusion and .NET
ColdFusion lets you access and use Microsoft .NET assembly classes as CFML objects. CFML applications can use
.NET assemblies in the following ways:
• Directly access and control Microsoft products, such as Word, Excel, or PowerPoint.
• Use existing .NET components.
• Use .NET assemblies that you create to leverage features that are difficult to use or not available in ColdFusion
or Java. (Because ColdFusion is a J2EE application, if you cannot code a feature in CFML, it is more efficient to create
it in Java than to use .NET.)
The .NET classes that your application uses do not have to be local; your ColdFusion application can access .NET
components that are located on remote systems, even systems that are located outside your firewall. Also, the
ColdFusion system does not require .NET run-time software installed to use remote .NET components, so
ColdFusion running on a UNIX, Linux, Solaris, or OS-X system can access and use .NET assemblies.
You can use the
cfobject tag or CreateObject function to create a reference to a .NET class object, by specifying
either
.NET or dotnet as the object type. You use the reference to access the .NET class fields and call the .NET class
methods. This technique provides a tightly coupled, stateful, efficient method for accessing .NET classes from
ColdFusion. As an alternative, your .NET application can make the class methods available as web services; however,
using a web service is less reliable, has lower performance, and is less scalable than using ColdFusion objects for the
.NET classes.
Note: .NET applications cannot access ColdFusion component functions directly. You can make the functions available
as web services by specifying remote access. For more information on creating ColdFusion web services, see “Using Web
Services” on page 900.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
951
Because you use the .NET assembly classes the same way that you use any other ColdFusion object, you do not have
to understand the details of .NET technology; you only have to understand how to use the specific .NET class that
you are accessing. Code that uses a .NET method can be as simple as the following lines:
<cfobject type = ".NET" name = "mathInstance" class = "mathClass"
assembly = "C:/Net/Assemblies/math.dll">
<cfset myVar = mathInstance.multiply(1,2)>
ColdFusion .NET access has the following additional features:
• If you make a change in the .NET assembly, ColdFusion automatically recognizes the change and uses that
version for the next invocation.
• Your application can access .NET assemblies running on multiple machines.
• You can secure the communication between ColdFusion and .NET by using SSL.
• Primitive data types are automatically mapped between ColdFusion and .NET data types.
How .NET access works
For ColdFusion to access .NET assemblies, ColdFusion .NET extension software must run on the system that hosts
the assemblies. A ColdFusion system that accesses only remote assemblies does not require the .NET extension. The
.NET extension software provides the .NET-side connectivity features that enable access to .NET assemblies,
including a .NET-side agent (which normally runs as the ColdFusion 8 .NET service) that listens for and handles
requests from the ColdFusion system.
On the ColdFusion system, the ColdFusion objects use Java proxies that act as local representatives of the .NET
classes. These proxies use binary TCP or SOAP-based HTTP communication to access a .NET-side agent. The agent
then uses a DLL to invoke the .NET assembly classes. This communication is required in all cases, even if ColdFusion
and the .NET assemblies are on the same system.
The following image shows how CFML-to NET access works:
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
952
If your .NET assemblies are on the local system, ColdFusion automatically creates and manages all required proxies
and configuration information. You must ensure only that the .NET extension is installed on your system and that
the ColdFusion 8 .NET Service is running; you can use the
cfobject tag or CreateObject function to access the
assemblies without any additional steps.
If the assemblies are on a remote system, you install and use the ColdFusion 8 .NET extension software on the .NET
system to create Java proxies for the .NET classes, and then move or copy them to the ColdFusion system. You must
also edit the JNBDotNetSide.exe.config file on the remote system to specify the .NET classes you use. The .NET
system requires the following .NET extension software:
• JNBDotNetSide.exe, the .NET-side agent that communicates with the ColdFusion system (normally run as the
ColdFusion 8 .NET service).
• JNBDotNetSide.exe.config, a configuration file that identifies the .NET assemblies that can be accessed by
ColdFusion.
• jnbproxy.exe and jnbproxyGui.exe, command-line and GUI-based programs that generate the Java proxies that
represent the .NET assemblies.
• Additional support files, including JNBShare.dll, which invoke the .NET assembly classes.
For information on installing the ColdFusion .NET extension, see Installing and Using ColdFusion.
Note: When you install a new .NET version, you must reinstall the ColdFusion .NET extension.
CFML Page
Invokes
Java Proxy
Uses
JNBCore.jar
(installed on all
ColdFuson
systems)
TCP/Binary or
HTTP/SOAP
communications
JNBDotNetSide.exe
(runs as a Windows
service)
JNBShare.dll
Uses
Invokes
.NET Assembly
.NET Side
ColdFusion Side
both sides can be
on a single system
JNBDotNetSide.
exe.config
Specifies
assembly classes
Application view
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
953
Accessing .NET assemblies
ColdFusion provides two methods for accessing .NET assemblies:
• A local access method for .NET objects that are installed on the ColdFusion system
• A remote access method for .NET objects located on other systems.
For both methods, you must install the ColdFusion .NET extension and run the ColdFusion 8 .NET service on the
system that hosts the assemblies. You do not need to install the extension or run the service on a ColdFusion system
that accesses only remote assemblies. For information on installing the ColdFusion .NET extension, see Installing
and Using ColdFusion.
Accessing local assemblies
For local access, ColdFusion automatically generates and uses proxies for the required .NET assemblies when you
first use the
cfobject tag or CreateObject function. ColdFusion caches the proxies for future use, so it does not
generate assembly proxies each time.
Usually when you are accessing local .NET assemblies, you do not have to override the default communication
configuration settings. Sometimes you might have to specify these settings, however. If other software on your
system uses the default 6086 port, for example, you must change the port number specification in the
jnbridge\DotNetSide.exe.config file, and you must specify the changed port number in your
cfobject tag or
CreateObject tag. For information on changing the port number specification, see “Configuring the .NET-side
system” on page 956,
To use the local access method, you need only to use the
cfobject tag or CreateObject function to create and
access the proxy. You can use the resulting ColdFusion object to construct the .NET object, call the .NET object’s
methods, and access its fields. For detailed information on using .NET classes, see “Using .NET classes” on page 957.
Accessing remote assemblies
The remote access technique accesses .NET assemblies by using TCP or HTTP to communicate with a .NET-side
agent on a remote system. You create proxy instances and call assembly methods as you do in the Local access
method, but you must first configure the remote .NET-side agent and, in most cases, the proxy classes that represent
the remote .NET classes.
Configure remote .NET access
1
On the remote system, install the ColdFusion 8 .NET integration software and run the .NET-side agent (see
Installing and Using ColdFusion).
2 If the .NET assemblies reside only on the remote system, generate proxy JAR files on that system that represent
the assemblies (see “Generating the Java proxy classes” on page 954). Then copy or move the proxy files to the local
system. If identical .NET assemblies also reside on the local system, you can skip this step.
3 Configure the .NET-side system for remote access (see “Configuring the .NET-side system” on page 956).
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
954
Generating the Java proxy classes
The Java proxy generation code requires direct access to the .NET assemblies to generate the proxy classes.
Therefore, if the system that runs your ColdFusion application does not have the assemblies installed, you must run
a tool on the .NET-side system to create the Java proxies. ColdFusion installs two proxy generation programs,
jnbproxyGui.exe and jnbproxy.exe in the jnbridge directory when you install the .NET services. The
jnbproxyGui.exe program is a Windows UI application, and the jnbproxy.exe program is a command line appli-
cation. Both programs have identical capabilities.
Note: If the system running the ColdFusion application has the assemblies installed, but must access remote versions of
the assemblies (for example, because of configuration differences), you do not need to manually generate the proxy
classes, and you can skip this step. Instead, specify the paths to the local .exe or .dll files in the
assembly attribute of the
cfobject tag (or CreateObject function) and specify the remote server in the server attribute. You must configure
the remote system for access, however.
On a ColdFusion system, the jnbproxyGui and jnbproxy programs are located in the cfroot\jnbridge directory. When
you use the stand-alone installer, the programs are located in the installDir\jnbridge directory.
This topic provides the basic information necessary to generate a proxy JAR file using the jnbproxyGui tool.
Additional information is available in the following locations:
• The jnbridge directory includes a jnbproxy.chm Windows Help file with more complete documentation on the
JNBridge technology that powers the ColdFusion .NET feature, including detailed information on both the
jnbproxyGui and jnbproxy programs.
• The jnbridge\docs subdirectory includes additional documentation, including users guide.pdf, a PDF version of
the information in the Help file.
Note: The JNBridge documentation includes information on features that are not supported in ColdFusion. ColdFusion,
for example, does not support access from .NET assemblies to ColdFusion or memory-only communication.
Using the jnbproxyGui tool
You use the jnbproxyGui program to generate a proxy JAR file.
Generate and install a proxy JAR
1
Start JNBProxyGui.exe.
2 The first time you run the program, it displays the Enter Java Options dialog box. Configure the options, and
click OK.
You can change the configuration settings at a later time by selecting Project > Java Options.
On a system with ColdFusion: If ColdFusion is currently running on this system, ensure that the Start Java
Automatically option, located on the right side of the JNBProxy Enter Java Options (Project > Java Options)
dialog box is cleared. Leave the default values for the other settings.
When you open an existing project, you might get a Restart Java Side pop-up warning with the message "You
must stop and restart the Java side before these changes to the classpath can take effect." You can ignore this
message and click OK to proceed.
When you start the program, the Java Options dialog box might appear. You do not have to make any changes;
click OK or Cancel to open the Launch JNBProxy dialog box.
In some cases, JNBProxyGui might behave as follows when the Start Java Automatically option is not selected.
On a system without ColdFusion: If ColdFusion is not currently running on the system, ensure the following
options, which are located on the right side of the interface, are set. Leave the default values for the other settings.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
955
• Ensure that the Start Java Automatically option is selected.
• Specify the java.exe file to use to compile the JAR file. You can use a Java 1.4 or 1.5 (J2SE 5.0) version of this
file.
• Specify the jnbcore.jar file. The ColdFusion server installer puts this file in the cfroot\lib directory. The J2EE
installer puts the file in the cf_webapp_root\WEB-INF\cfusion\lib directory.
• Specify the bcel.jar file. The ColdFusion server installer puts this file in the cfroot\lib directory. The J2EE
installer puts the file in the cf_webapp_root\WEB-INF\cfusion\lib directory.
3 In the Launch JNBProxy dialog box, select Create New Java > .NET Project, and click OK.
4 In the main Java proxy generation interface, set up and build a project:
a If you have not already done so, you must add the directory that contains your assemblies to the JNBProxy
your project. Select Project >Edit Assembly List. In the Assembly List dialog box, click the Add button. In the
New Assembly List Element dialog box, navigate to the directory that contains your assemblies. Select the
directory (or directories) in the tree, and click OK. Then click OK in the Edit Assembly List dialog box.
b Open the Locate Assembly File dialog box (Project > Add Classes From Assembly File) and navigate to the
directory that you added to the assembly list in step a. Select the assembly file or files that contain classes that
require proxies and click OK.
c The classes in the selected file, and other .NET core classes on which they depend, appear in the
Environment pane. Select all classes for which you want proxies in your JAR file, and click the Add+ button to
add the selected classes and all supporting classes.
d In the Exposed Proxies list, select the classes to include in the JAR file. Normally, you should select all the
listed classes, which ensures that all required classes are included.
e Select Project > Build from the main menu. In the Save Generated Proxies dialog box, specify the location
and JAR file in which to save the generated proxies, and click Save.
f After the project is built, select File > Save Project and specify the file in which to save your project.
The next time you run the jnbproxyGui program, you can select your project and reuse your previous
settings, including the Assembly List.
5 Copy the JAR file to a directory on your ColdFusion system. You specify this path in the cfobject tag assembly
attribute.
Supporting classes
JNBProxy can generate proxies not only for the .NET classes that are explicitly listed, but also for supporting classes.
A supporting class for a given .NET class is any class that might be needed as a direct or indirect result of using that
.NET class. For a given .NET class, supporting classes include all of the following:
• The class.
• The class’s superclass or superinterface (if it exists) and all of its supporting classes.
• The class’s implemented interfaces (if any) and all of their supporting classes.
• For each field in the class:
• The field’s class and all of its supporting classes.
• For each of the field’s index parameters, the parameter’s class and all of its supporting classes.
• For each method in the class:
• The method’s return value’s class (if any) and all of its supporting classes.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
956
• For each of the method’s parameters, the parameter’s class and all of its supporting classes.
• For each constructor in the class, for each of the constructor’s parameters, the parameter’s class and all of its
supporting classes.
Unlike Java, where supporting classes include exceptions declared to be thrown by methods, .NET supporting classes
don’t include thrown exceptions, because they are not declared in advance.
The number of supporting classes depends on the classes explicitly listed, but there are often 200-250 classes. Usually
you generate all supporting classes. However, there are situations where, to save time or space, you can generate only
those classes explicitly specified, without supporting classes.
If a proxy for a supporting class has not been generated, and a proxy for such a class is later needed when the proxies
are used, the proxy for the nearest superclass to the required class is used instead. If that proxy hasn’t been generated,
the proxy for that superclass’s superclass will be used if it has been generated, and so forth, until the proxy for
System.Object (which is always generated) is encountered. Thus, even with an incomplete set of proxies, code will
execute, although functionality and other information may be lost.
In the jnbproxyGui tool, when you click the Add button, the list includes only the explicitly listed classes. When you
click the Add+ button. the list also includes the supporting classes. In the jnbproxy command line program, the
default command generates proxies for the supporting classes; use the
/ns option to override this default.
Configuring the .NET-side system
To configure the .NET-side system, you edit the jnbridge\JNBDotNetSide.exe.config configuration file in the
following ways:
• For local assemblies, you must edit this file only if you do not use the default port, or if you use SSL security.
• For a .NET assembly on a remote machine, you must register the assemblies in this file to make it accessible to
ColdFusion.
Edit the configuration file
1
Ensure the following lines are in the <configSections> subsection of the <configuration> section:
<jnbridge>
<javaToDotNetConfig scheme="Protocol" port="local port number"
useSSL="true|false" certificateLocation="server certificate path"/>
</jnbridge>
• The scheme attribute specifies the communications protocol, and must be jtcp or http.
• The port number is the port of the .NET-side agent, normally 6086.
• The useSSL attribute specifies whether to use SSL for secure communications. The attribute is optional; the
default is to not use SSL.
• The certificateLocation attribute specifies the location of the server SSL certificate. It is required only
if the
useSSL attribute is true.
These settings must be the same as the corresponding attributes in your
cfobject tag.
2 If the .NET assemblies are on a remote system, specify the assemblies that ColdFusion will access by adding the
following elements inside the <jnbridge> section.
<assemblyList>
<assembly file=”path to assembly or fully qualified name”/>
</assemblyList>
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
957
3 Stop and restart the .NET-side agent, if it is running. For example, on a ColdFusion system, restart the
ColdFusion 8 8 .NET Service. Your ColdFusion application can now access the .NET classes that you configured.
The following example is a bare-bones JNBDotNetSide.exe.config file that specifies a .NET-side TCP server config-
uration. The server communicates by using TCP binary mode and listens on port 6086. Java clients can access classes
from the C:\F\x.dll assembly and from System.Windows.Forms, which is in the GAC:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<sectionGroup name="jnbridge">
<section name="dotNetToJavaConfig"
type="System.Configuration.SingleTagSectionHandler"/>
<section name="javaToDotNetConfig"
type="System.Configuration.SingleTagSectionHandler"/>
<section name="tcpNoDelay"
type="System.Configuration.SingleTagSectionHandler"/>
<section name="javaSideDeclarations"
type="System.Configuration.NameValueSectionHandler"/>
<section name="assemblyList"
type="com.jnbridge.jnbcore.AssemblyListHandler, JNBShare"/> <<Hal: I added
the closing " after JNBShare, OK? there wasn’t a closing " LA 3.6.07>>
</sectionGroup>
<jnbridge>
<javaToDotNetConfig scheme="jtcp" port="6086"/>
<assemblyList>
<assembly file="C:\F\x.dll"/>
<assembly file="System.Windows.Forms, Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</assemblyList>
</jnbridge>
</configuration>
Using .NET classes
You use .NET assembly classes the same way you use Java and other objects that you create using the cfobject tag
or
CreateObject function. In the simplest case, your application code only has to use the following format to
include a local .NET class method:
<cfobject type = ".NET" name = "mathInstance" class = "mathClass"
assembly = "C:/Net/Assemblies/math.dll">
<cfset myVar = mathInstance.multiply(1,2)>
Using CFScript and the CreateObject function, you can do the following:
<cfscript>
mathInstance = CreateObject(".NET", "mathClass",
"C:/Net/Assemblies/math.dll");
myVar = mathInstance.multiply(1,2);
</cfscript>
Note: You cannot load two DLLs with same fully qualified name. ColdFusion always uses the first DLL that it accesses
until the server is restarted. For example, if page1.cfm uses c:\dev\a.dll and page2.cfm uses c:\dev2\a.dll, and both DLLs
have the same fully qualified name, the first DLL file to be loaded remains loaded, and both CFML pages use it.
When you create objects and access class methods and fields, and convert data types between ColdFusion and .NET,
you must be aware of the considerations and limitations described in the following sections:
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
958
• Data type conversion considerations described in “Converting between .NET and ColdFusion data types” on
page 958
• Limitations described in the “Limitations” section of cfobject: .NET object in the CFML Reference.
Instantiating objects and calling class constructors
When you use the cfobject tag to create a .NET object, ColdFusion does not create an instance of the object.
ColdFusion creates the object instance in either of the following cases:
• If the class has a default constructor, ColdFusion automatically calls the constructor when you first invoke a non-
static method of the object.
• If the class does not have a default constructor, or if the class has multiple constructors and you do not want to
use the default, call the special
init method of the ColdFusion object. The cfobject tag automatically creates init
methods for all class constructors. Using the
init method causes ColdFusion to call the class constructor with the
corresponding number and types of parameters. For example, the following tags cause ColdFusion to call the
MyClass constructor that takes two integer parameters:
<cfobject type=".NET" name="myObj" class="com.myCo.MyClass"
assembly="c:\assemblies\myLib.dll">
<cfset myObj.init(10, 5)>
Note: ColdFusion does not create instances of objects if you use only their static methods.
Calling methods
You call .NET methods in the same way that you use any other ColdFusion object methods. For example, if the
MyClass class has a
getName method that takes a numeric ID and returns a name, you would call the method as
follows:
<cfset theID="2343">
<cfset userName=mObj.getName(theID)>
Getting and setting fields
You can access and change public fields of any .NET class by calling the following methods:
Get_fieldName()
Set_fieldName(value)
For example, if the .NET class has a public field named accountID, you can access and change its value by using the
Get_accountID() and Set_accountID() methods, as follows:
<cfobject type=".NET" class="com.myCo.MyClass"
assembly="c:\assemblies\myLib.dll" name="myObj">
<cfset theAccount=myObj.Get_accountID()>
<cfset myObj.Set_accountID(theAccount + 1)>
You can access, but not modify final fields, so you can only call Get_fieldName() for these fields.
Converting between .NET and ColdFusion data types
Accessing .NET classes requires a Java proxy on the ColdFusion system and .NET code on the target system, so data
must be converted among ColdFusion, Java, and .NET (to be exact, Microsoft Intermediate Language, or MSIL) data
types. ColdFusion converts data types automatically. Usually, you do not have to take any special steps to ensure
correct conversion. There are some conversion limitations, and in some cases you must explicitly specify a data type
when you call a method in a .NET proxy object.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
959
The following paragraphs describe some the data conversion issues and how to handle them. For a detailed specifi-
cation of how ColdFusion converts among ColdFusion data, Java data types, and .NET data types, see
cfobject:
.NET object
in the CFML Reference.
Data type conversion rules and techniques
ColdFusion converts data automatically among ColdFusion, Java, and CLR data types. The following table indicates
how ColdFusion converts among .NET Common Language Runtime (CLR) primitive and standard data types, the
Java data types used in the proxies to represent CLR data types, and ColdFusion data types in your CFML appli-
cation.
.NET type Java type ColdFusion type
sbyte byte Integer
byte short Integer
short short Integer
ushort int Integer
int int Integer
uint long Number
char char Integer or string
long long Number
ulong float Number
float float Number
double double Number
The returned number retains greater precision than is normally displayed in ColdFusion. Use the
PrecisionEvaluate function to access and display the full precision of a returned double
value. You can also pass a value with full double precision to a .NET method.
bool boolean Boolean
enum Not converted, but enumerator elements can be accessed directly by using the format
Enumerator_variable.enumerator, as in MyColor.Red
array array Array
string String String
System.Collec-
tions.ArrayList
java.util.ArrayList Array
Note: ColdFusion converts from .NET type to ColdFusion type only, it does not convert ColdFu-
sion Arrays to .NET ArrayLists.
System.Collec-
tions.Hashtable
java.util.Hash-
table
Structure
Note: ColdFusion converts from .NET type to ColdFusion type only, it does not convert ColdFu-
sion Structures to .NET Hashtables
System.Data.DataT-
able
Query
Note: ColdFusion converts from .NET type to ColdFusion type only, it does not convert ColdFu-
sion Queries to .NET DataTables
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
960
Using decimal numbers
You must us e t h e JavaCast function to convert ColdFusion data into BigDecimal format before you pass the value
to a .NET function, as in the following example:
<cfset netObj.netFunc(javacast("bigdecimal","439732984732048"))>
ColdFusion automatically converts returned decimal and System.Decimal values to ColdFusion string representa-
tions.
Ensuring decimal and date/time conversions
ColdFusion converts .NET decimal or System.Decimal types only if the proxy for System.Decimal is a value type
proxy. Similarly, it converts .NET System.DateTime values to ColdFusion Date-time values only if the proxy for
System.DateTime is a value type proxy. The ColdFusion server always uses value proxies when it generates these
proxies. If you use the JNBProxyGUI.exe tool to generate the proxy, however, you must make sure to generate the
proxy for System.Decimal as value type.
Converting data to System.Object type
When a .NET method specifies System.Object (as opposed to a specific Object subclass, such as System.Boolean)
as the argument type, and you want to pass primitive values as arguments to that method, you must use the
javacast function to identify the data conversion. Once ColdFusion knows the data type, it automatically converts
to the appropriate .NET type. Here is the table that describes the conversion rule from ColdFusion type to .NET type.
System.DateTime java.util.Date Date/time
decimal
System.Decimal
java.math.BigDe
cimal
String representation of the decimal number.
For details on using decimal numbers, see “Using decimal numbers” on page 960.
System.Object If a .NET argument is of type System.Object, ColdFusion Strings are converted directly. Other
types require using the JavaCast function.
ColdFusion cannot convert System.object instances returned by .NET methods to ColdFusion
types, but you can access them using the Object methods.
For detailed information, see “Converting data to System.Object type” on page 960.
.NET Type Type used in javacast
bool / System.Boolean boolean
bool[] / System.Boolean[] boolean[]
char / System.Char char
char[] / System.Char[] char[]
double / System.Double double
double[] / System.Double[] double[]
float / System.Single float
float[] / System.Single[] float[]
int / System.Int32 int
int[] / System.Int32[] int[]
long / System.Int64 long
long[] / System.Int64[] long[]
.NET type Java type ColdFusion type
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
961
Note: You do not need to use a JavaCast function to convert ColdFusion string variables. They are automatically be
converted to .NET System.String.
You must create special objects for .NET primitive unsigned data types, such as byte (unsigned byte), ushort
(unsigned short), uint (unsigned int) and ulong (unsigned long), for which there are no corresponding java types.
The following table lists the .NET primitive types and the corresponding class you must use.
You must use the
createObject function or cfobject tag to create these special objects, in the same manner as you
create other .NET classes, before you use them in your assignment statement. For example, the following line creates
a ushort representation of the value 100:
<cfset boxedUShort = createObject(".NET". "System.BoxedUShort").init(100)>
The following example creates a System.Hashtable object and populates it with examples of all types of primitives.
<! create a .NET Hashtable >
<cfset table = createObject(".NET", "System.Collections.Hashtable")>
<! call HashTable.add(Object, Object) method for all primitives >
<cfset table.add("shortVar", javacast("short", 10))>
<cfset table.add("sbyteVar", javacast("byte", 20))>
<cfset table.add("intVar", javacast("int", 123))>
<cfset table.add("longVar", javacast("long", 1234))>
<cfset table.add("floatVar", javacast("float", 123.4))>
<cfset table.add("doubleVar", javacast("double", 123.4))>
<cfset table.add("charVar", javacast("char", 'c'))>
<cfset table.add("booleanVar", javacast("boolean", "yes"))>
<cfset table.add("StringVar", "Hello World")>
<cfset table.add("decimalVar", javacast("bigdecimal", 123234234.505))>
<! call HashTable.add(Object, Object) for unsigned primitive types. >
<cfset boxedByte = createObject(".NET", "System.BoxedByte").init(10)>
<cfset table.add("byteVar", boxedByte)>
<cfset boxedUShort = createObject(".NET", "System.BoxedUShort").init(100)>
<cfset table.add("ushortVar", boxedUShort)>
<cfset boxedUInt = createObject(".NET", "System.BoxedUInt").init(123)>
<cfset table.add("uintVar", boxedUInt)>
<cfset boxedULong = createObject(".NET", "System.BoxedULong").init(123123)>
<cfset table.add("ulongVar", boxedULong)>
sbyte / System.Sbyte byte
sbyte []/ System.Sbyte[] byte []
short / System.Int16 short
short[] / System.Int16[] short[]
System.Decimal bigdecimal
System.String String
.NET type Class used in cfobject/createObject
byte / System.Byte System.BoxedByte
ushort / System.UInt16 System.BoxedUShort
uint / System.UInt32 System.BoxedUInt
ulong / System.UInt64 System.BoxedULong
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
962
<cfdump var="#DotNetToCFType(table)#">
Any other .NET objects can be passed as it is.
Handling ambiguous type conversions
ColdFusion cannot determine the correct data type conversion if a method has multiple signatures with the same
number of parameters that differ only in the parameter data types. In this case, use the
JavaCast method to convert
the ColdFusion data to the Java type that corresponds to the .NET type.
For example, if a .NET class has methods myFunc(ulong) and myFunc(int), use the
JavaCast method to convert
your ColdFusion variable to the Java float or int data type, as the following line shows:
myFunc(JavaCast(int, MyVar));
Similarly, if a .NET class has methods myFunc(int) and myFunc(String), use the JavaCast method to convert your
ColdFusion variable to the Java int or String data type, as shown in the following line:
myFunc(JavaCast(String, "123");
In some cases, the JavaCast function cannot eliminate ambiguity because a single Java type corresponds to multiple
.NET types. In these cases, ColdFusion creates a proxy with only one method, which uses the .NET data type that
corresponds directly to a Java type.
For example, if the .NET class has methods myFunc(ulong) and myFunc(float), the generated proxy has only one
method. This method calls myFunc(float), because the Java float type used to handle ColdFusion floating point
numbers corresponds directly to the .NET float type. In this case, you can never call the .NET myFunc(ulong)
method.
Working with complex .NET data types
When you use complex .NET data such as Hashtable, ArrayList and DataTable, ColdFusion normally automatically
converts the data to the corresponding ColdFusion datatype: structure, array and query, respectively . When you
work with this data you take specific actions to enable the proper access and conversion of the data, as follows:
• You must use associative array notation to properly access .NET Hashtable data from ColdFusion
• You cannot use ColdFusion variables directly in parameters that take Hashtable, ArrayList or DataTable input.
• You can disable automatic conversion of complex .NET data to ColdFusion types.
• You can manually convert complex .NET data to ColdFusion types.
Using Hashtable data in ColdFusion
.NET Hashtables are case sensitive, but most methods of ColdFusion structure access are case insensitive. Only
associative array notation of the form
structName["keyName"] is case sensitive. When .NET Hashtables are
converted to CF structure, the entire data set is converted, even if the element keys differ only in case. Therefore, to
get the values of the keys that differ only in case, you must use associative array notation.
The following example shows this issue. It creates a Hashtable object with three entries whose key values vary only
in case. In the example, output using dot-delimited structure notation always returns the same value, corresponding
to the all-uppercase key, but associative array notation returns the correct result.
<! Create a Hashtable and convert it to a ColdFusion structure. >
<cfset table = createObject(".NET", "System.Collections.Hashtable")>
<cfset table.add("Key", "Value1")>
<cfset table.add("KEY", "Value2")>
<cfset table.add("key", "Value3")>
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
963
<cfset cftable = DotNetToCFType(table)>
<cfdump var="#cftable#">
<h3>Using dot notation</h3>
Key : <cfoutput>#cftable.Key#</cfoutput><br>
KEY : <cfoutput>#cftable.KEY#</cfoutput><br>
key : <cfoutput>#cftable.key#</cfoutput><br>
<p>
<h3>Using associative array notation</h3>
Key : <cfoutput>#cftable["Key"]#</cfoutput><br>
KEY : <cfoutput>#cftable["KEY"]#</cfoutput><br>
key : <cfoutput>#cftable["key"]#</cfoutput><br>
Using .Net ArrayList in ColdFusion
ColdFusion converts System.Collections.ArrayList objects to ColdFusion arrays, and you can perform all standard
ColdFusion array operations on them. The following example shows this usage:
.Net Code:
public ArrayList getList(){
ArrayList myAL = new ArrayList();
myAL.Add("Hello");
myAL.Add(1);
myAL.add(true);
Return AL;
}
ColdFusion Code:
<cfset cflist = netObject.getList()>
<cfloop array="#cflist#" index="item">
<cfoutput>#item#</cfoutput><br>
</cfloop>
<cfif cflist[3]>
<cfoutput>3rd element in the list is true</cfoutput>
</cfif>
Using ADO.Net DataTable in ColdFusion
ColdFusion converts System.Data.DataTable objects to ColdFusion query objects, and you can perform all standard
ColdFusion query operations on them. The following example shows this usage:
.Net code:
public DataTable datasetMethod()
{
//conn string
string connectionString = " ";
//connection
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(@"SELECT * FROM [tblEmployees]", connection);
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;
}
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
964
}
ColdFusion code:
<cfset query1 = netObject.datasetMethod()>
<cfoutput query="query1">
Query1.CurrentRow = #query1.CurrentRow#<br>
</cfoutput>
Using ColdFusion complex types in .NET input parameters
When a .NET method returns an ArrayList, Hashtable or DataTable, ColdFusion automatically converts it to a
ColdFusion array, structure or query, respectively. However ColdFusion does not automatically convert from
ColdFusion data types to these .NET types. (ColdFusion does automatically convert ColdFusion arrays to .Net array
types.) Therefore, you cannot use ColdFusion variables directly as input parameters to .NET object instance methods
that require .NET System.Collection.ArrayList, System.Collection.Hashtable, or System.Data.DataTable types.
Instead you must create instances of these .NET types and populate them with the required data before you pass
them to the .NET method. For an example of creating and populating a System.Collection.Hashtable object, see the
example at the end of the “Converting data to System.Object type” section.
Disabling automatic conversion of complex .NET data
You can disable automatic conversion of .NET System.Collections.Hashtable,
System.Collections.ArrayList or System.Data.DataTable objects to the corresponding ColdFusion
structure, array or query objects. You might want to do this under the following circumstances:
• If a collection or DataTable returned by a .NET method is very large and you only want a small subset of the data.
If auto conversion is enabled, ColdFusion creates a data structure with all the object’s fields. This might take signif-
icant time and resources, because ColdFusion must invoke .NET methods internally to get each of the fields. You can
disable the automatic conversion and retrieve the fields or data from .NET objects like any other objects.
• If you invoke a .NET method that returns a complex variable, and then pass the variable to another .NET method
as argument. If automatic conversion is enabled, you cannot pass the Hashtable object from the first method directly
to the second method.
To disable automatic conversion, set the JVM coldfusion.dotnet.disableautoconversion system property to true. For
example, in a ColdFusion stand-alone server, or if you use JRun as your J2EE server, include the following setting in
the JVM.config file:
-Dcoldfusion.dotnet.disableautoconversion=true
Manually converting complex .NET objects
Use the DotNetToCFType function to convert a System.Collections.Hashtable,
System.Collections.ArrayList or System.Data.DataTable object to a ColdFusion structure, array or query
respectively when either of the following circumstances are true:
• You have set the coldfusion.dotnet.disableautoconversion system property to true.
• Automatic conversion is enabled, you created the complex .NET object by using the createObject function or
cfobject tag, and you want to convert this object into the corresponding ColdFusion representation.
For an example of using the function, see
DotNetToCFType in the CFML Reference.
Using .NET objects
.NET fields and return values with class types are available in ColdFusion as .NET objects. You can use the object’s
methods to access object data and make it available to ColdFusion using supported data types.
ADOBE COLDFUSION 8
ColdFusion Developer’s Guide
965
The following example gets information about a system’s drives. It calls the System.IO.DriveInfo.GetDrives() method
to get an array of System.IO.DriveInfo objects, one per drive. It then calls the object methods to get specific infor-
mation about the drives, and displays the information. The example uses a
cfdump tag to simplify the code.
Note: The System.IO.DriveInfo is not included in the .NET 1.x framework. It is included in .NET 2.0 and later frame-
works. For information on determining the .NET framework, see “Determining and changing the .NET version” on
page 971.
<! Create a query for the drive information results. >
<cfset result=QueryNew("name,type,isready,format,label,totalsize,freespace"
,"varchar,varchar,bit,varchar,varchar,double,double")>
<! Create a .NET System.IO.DriveInfo object. >
<cfobject type=".NET" name="sidiClass" class="System.IO.DriveInfo">
<! Get the drives. >
<cfset drives=sidiClass.GetDrives()>
<! Loop through drives. >
<cfloop from="1" to="#ArrayLen(drives)#" index="i">
<! Add a row to the query >
<cfset QueryAddRow(result)>
<! Get the drive name, type, and ready flag. >
<cfset QuerySetCell(result, "name", drives[i].Get_Name())>
<cfset QuerySetCell(result, "type",
drives[i].Get_DriveType().ToString())>
<cfset QuerySetCell(result, "isready", drives[i].Get_IsReady())>
<! Get extra details ONLY if the drive is ready. >
<cfif drives[i].Get_IsReady()>
<cfset QuerySetCell(result, "format", drives[i].Get_DriveFormat())>
<cfset QuerySetCell(result, "label", drives[i].Get_VolumeLabel())>
<cfset QuerySetCell(result, "totalsize", drives[i].Get_TotalSize())>
<cfset QuerySetCell(result, "freespace",
drives[i].Get_AvailableFreeSpace())>
</cfif>
</cfloop>
<cfdump var="#result#">
.NET Interoperability Limitations
ColdFusion .NET interoperability has the following limitations
• You cannot invoke methods with pointers as arguments or the return type.
• You cannot invoke methods that take Out parameters.
• ColdFusion can only convert from System.Data.DataTable, System.Collection.Hashtable and
System.Collection.ArrayList to ColdFusion data types. ColdFusion cannot convert from ColdFusion queries, struc-
tures, and arrays to these System data types; however, it can convert from ColdFusion arrays to the CLR array type.
Therefore, you cannot pass structures or queries directly to .NET methods.
• You cannot access .NET UI components.
• You cannot use callbacks (events and Delegates) from .NET side.
• ColdFusion cannot determine the correct data type conversion if a method has multiple signatures that have the
same number of parameters and differ only in the parameter data types. In this case, use the
JavaCast method to
convert the ColdFusion data to the Java type that corresponds to the .NET type.