July 30, 2005
Making Your ColdFusion and Java Applications More Platform Independent (Part III)
Making Your ColdFusion and Java Applications More Platform Independent (Part III)
Two years ago (has it really been that long?!), I made a couple of posts about how to make your ColdFusion and Java applications more platform independent. The first post covered the importance of case consistency, and the second talked about not hard-coding path separators since they are different on different platforms. Well, all this time later, I actually have a third piece of advice: don't hard-code new line characters.
I'm switching my development environment over from OS X to Windows (I haven't used Windows consistently in many years, so I figured it was time to give it a try again), and while trying to get MXNA running locally, I came across a bug that I'd never seen in development (on OS X) or on production (Linux). The problem was this line of code:
<cfset blArray = listToArray(blacklist, chr(10))/>
The code is trying to convert a line-separated list into an array. On OS X and Linux, it works fine since the new line character is "line feed", or chr(10), or \n, but on Windows, the code didn't work because a new line is "line feed" and "carriage return", or chr(10) & chr(13), or \n and \r. So rather than ever having to worry about this again, I used a little Java trick to make the code run in any environment. Now it looks like this:
<cfset blArray = listToArray(blacklist, createObject("java", "java.lang.System").getProperty("line.separator"))/>
Even with a language like Java (and hence, ColdFusion), if you want your code to be truly platform independent, it takes a little work. The good news is that once that was fixed, MXNA was up and running in my development environment perfectly.
Posted by cantrell at 10:50 AM. Link | Comments (8) | References
July 2, 2003
How to Snoop on ColdFusion Data Types
Last week, I made a couple of posts about ColdFusion Arrays, and how they are actually java.util.Vectors, which means that you can convert them to Java arrays by calling toArray(). How did I figure that out? I didn't ask the ColdFusion engineers. That's cheating. The first thing I did was find out what type of class we are actually dealing with when we have a reference to an array. The Java object "Object" (which all objects extend) has a method called getClass() which returns the runtime class of an object. Calling toString() on the class (or simply the act of outputting it, which automatically calls toString()) will reveal the class name:
<cfset cfArray = arrayNew(1)/>
<cfset cfArray[1] = "c"/>
<cfset cfArray[2] = "b"/>
<cfset cfArray[3] = "a"/>
<html>
<cfoutput>
#cfArray.getClass()#
</cfoutput>
</html>
The result of the code above is:
class coldfusion.runtime.Array
So now I know that I'm dealing with a coldfusion.runtime.Array, however that information doesn't do me any good by itself. What I need to know is what a coldfusion.runtime.Array really is, and what its public interface looks like. That's where "javap" comes in. javap is a program that comes installed with your JDK that most people actually don't know about. I don't know what the "p" stands for (any ideas?), but javap is essentially a Java class disassembler. Running it against any class in your classpath will, by default, output public and protected method signatures along with other class information (use the -private flag to see private method signatures). If you have java installed and in your path, at the command line, type:
javap java.lang.String
And you will get something like:
Compiled from String.java
public final class java.lang.String extends java.lang.Object implements
java.io.Serializable, java.lang.Comparable, java.lang.
CharSequence {
public static final java.util.Comparator CASE_INSENSITIVE_ORDER;
public java.lang.String();
public java.lang.String(java.lang.String);
public java.lang.String(char[]);
public java.lang.String(char[],int,int);
public java.lang.String(byte[],int,int,int);
public java.lang.String(byte[],int);
public java.lang.String(byte[],int,int,java.lang.String)
throws java.io.UnsupportedEncodingException;
public java.lang.String(byte[],java.lang.String) throws
java.io.UnsupportedEncodingException;
public java.lang.String(byte[],int,int);
public java.lang.String(byte[]);
public java.lang.String(java.lang.StringBuffer);
java.lang.String(int,int,char[]);
public int length();
...
}
So to find out more about coldfusion.runtime.Array, I used the following command:
javap -classpath /path/to/your/cfusion.jar coldfusion.runtime.Array
The output is:
No sourcepublic final class coldfusion.runtime.Array extends java.util.Vector {
public coldfusion.runtime.Array();
public coldfusion.runtime.Array(int);
static coldfusion.runtime.Array copy(coldfusion.runtime.Array);
static coldfusion.runtime.Array copy(java.util.List);
public int getDimension();
...
}
Since I could see from the output above that coldfusion.runtime.Array extends java.util.Vector, I knew that I had access to all of Vector's public methods, as well, such as toArray(), which was precisely the method I was looking for.
Posted by cantrell at 12:45 PM. Link | Comments (4) | References
June 26, 2003
Passing ColdFusion Arrays to Java
There were some comments on my weblog yesterday about using Java to sort ColdFusion arrays. The only problem is that you can't pass ColdFusion arrays into Java where Java is expecting an Array. Why? Because ColdFusion arrays aren't Java Arrays. They are, in fact, java.util.Vectors. Fortunately, it is easy to get an Array from a java.util.Vector. The following code demonstrates how to turn a ColdFusion array into a Java Array, and how to use Java to sort it:
<cfset cfArray = arrayNew(1)/>
<cfset cfArray[1] = "c"/>
<cfset cfArray[2] = "b"/>
<cfset cfArray[3] = "a"/>
<html>
<cfscript>
// Since CF arrays are Vectors, use toArray to turn
// them into Arrays.
jArray = cfArray.toArray();
// Iterate through the array to see that it is not sorted.
writeOutput("Unsorted...<br>");
for (i = 1; i le arrayLen(jArray); i = i + 1)
{
writeOutput(jArray[i] & "<br>");
}
// Use Java to sort the array.
Arrays = createObject("java", "java.util.Arrays");
Arrays.sort(jArray);
// Interate through the array again. It's sorted!
writeOutput("<br>Sorted...<br>");
for (i = 1; i le arrayLen(jArray); i = i + 1)
{
writeOutput(jArray[i] & "<br>");
}
</cfscript>
</html>
Posted by cantrell at 11:17 AM. Link | Comments (5) | References
June 13, 2003
Flash as an Alternative to JSP and Applets
In honor of JavaOne, I wrote a DevNet article on integrating Macromedia Flash and Java. It's pretty high-level (there are no code examples), but it pretty thoroughly discusses the capabilities of Flash and Flash Remoting, and the advantages of integrating Flash with Java. It also points to plenty of resources to help you get started. If this is something that you have considered, you might want to check it out.
Posted by cantrell at 12:27 PM. Link | References
June 11, 2003
ColdFusion MX Achieves "Java Verified" Status
Check out this story on Yahoo:
Macromedia ColdFusion MX Now 'Java Verified' for Portability Across J2EE Application Servers
An excerpt from the article:
Macromedia today announced that Macromedia(R) ColdFusion(R) MX has achieved "Java Verified" status under the Sun Microsystems Java Verification Program. The Java Verification Program is designed to identify enterprise applications developed with Java 2 Platform, Enterprise Edition (J2EE) technology that are intended to be portable across different implementations of J2EE.
You can all officially start thinking of yourselves as Java developers now!
Posted by cantrell at 3:49 PM. Link | Comments (4) | References
May 12, 2003
TheServerSide Features Talk By Macromedia Software Architect
TheServerSide.com is featuring a talk by Sean Neville, the JCP Executive Committee representative for Macromedia and Flash Remoting software architect. From TheServerSide's site:
Sean talks about Rich Internet Applications (RIAs), how they can be used to aggregate the business tier and enterprise applications using the client and looks at architectural approaches and technologies used for designing RIAs. He discusses how the J2EE Petstore was implemented in Flash, how the Flash Remoting product enables interoperability between J2EE and rich clients, and examines why vendors are trying to attract a new 'VB-style' group of developers. He also looks at changes that need to occur in the industry for RIAs to become mainstream.
Check it out here:
http://www.theserverside.com/events/index.jsp
Posted by cantrell at 1:48 PM. Link | References
May 6, 2003
Tons of New ColdFusion Content on DevNet
Macromedia just published several very high-quality ColdFusion (with a little Java thrown in) articles on DevNet:
Advanced ColdFusion: Simplicity Is Just the Start of It
Ben Forta
http://www.macromedia.com/devnet/logged_in/bforta_advcf.html
Building ColdFusion MX and J2EE Hybrid Applications
Drew Falkman
http://www.macromedia.com/devnet/mx/coldfusion/j2ee/articles/hybrid.html
Controlling Database Transactions in ColdFusion MX
Simon Horwith
http://www.macromedia.com/devnet/mx/coldfusion/articles/cftransaction.html
Improving Performance of Rich Internet Applications with Flash Communication Server MX
Giacomo 'Peldi' Guilizzoni
http://www.macromedia.com/devnet/mx/flashcom/articles/improving_ria.html
Building an Object-Oriented User Interface in ColdFusion MX
Dave Friedel
http://www.macromedia.com/devnet/mx/coldfusion/articles/oo_interface.html
Caching in ColdFusion
Matt Boles
http://www.macromedia.com/devnet/mx/coldfusion/articles/cfcaching.html
Posted by cantrell at 11:40 AM. Link | References
April 28, 2003
How Equals Works in Java
I saw some confusion about this matter on a list this morning, so I thought I'd clarify things here:
The object "Object" which all other Java objects extend has an equals method which allows you to check to see if two objects are equal, which means you call equals on any object you want. Objet's implementation of equals does the following (from the documentation):
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values xand y, this method returns true if and only if x and y refer to the same object ( x==y has the value true ).
When you compare two instances using ==, you are actually comparing their memory addresses to see if they are references to the same object. This is usually not very useful in the normal course of programming. Whether an object is equal to another object is pretty context-specific, meaning that it depends on the types of objects that you are comparing. Strings are a pretty straightforward case. If one string equals "abc" and another string equals "def", then if you check to see if they are equal by calling the equals method, it should return false. But if one string equals "abc" and the other string equals "abc", you don't want to compare the memory addresses of the two instances (since they will be different), but rather you want to compare the sequence of characters. Therefore, the String object override's Objet's equals method with it own implementation which simply compares the sequence of characters. Here's some code to illustrate the point:
This is true:
String a = "Christian Cantrell";
String b = "Christian Cantrell";
if (a.equals(b)) {
// This code will be executed.
}
But this is false:
if (a == b) {
// This will evaluate to false.
// Different memory addresses.
// Do this only to check to see if two
// variables point to the same object instance.
}
This is true:
if (a == a) {
// True because you are comparing the same instance.
}
And finally, this is also true:
b = a;
if (a == b) {
// True because you are comparing the same instance.
}
Many other objects override the equals method so that it makes sense contextually. I'll post more information tomorrow.
Posted by cantrell at 1:05 PM. Link | Comments (3) | References
April 23, 2003
Java Weblogs
I would like to get a good collection of Java weblogs posted here and aggregated into MXNA. Anybody have any favorites?
Posted by cantrell at 5:10 PM. Link | Comments (13) | References
April 15, 2003
CFMX for J2EE License Transfer Program Extended
Anyone interested in going from ColdFusion Server to CFMX for J2EE should check this out. From Macromedia's website:
"For a limited time, Macromedia ColdFusion Server Enterprise customers can transfer their licenses to ColdFusion MX for J2EE and receive up to a 30% discount through the Macromedia Volume License Program (MVLP).
Now, ColdFusion Server 4.5 (and later) Enterprise Edition (English version) customers can begin developing, deploying, and migrating their ColdFusion applications on their preferred J2EE application server at a significant savings."
Offer good through 6/31/2003. Details here:
http://www.macromedia.com/software/coldfusion/j2ee/special/license_transfer/
Posted by cantrell at 2:36 PM. Link | Comments (1) | References
April 3, 2003
Readers' Choice Awards - Cast Your Votes!
The Java Developer's Journal is currently holding it's sixth Readers' Choice Awards. ColdFusion MX has been nominated for both "Best Team Development Tool" and "Best J2EE Application Development Framework". JRun was nominated as "Best Java Application Server". Distinctions like these can be a big win for us all! Cast your vote here:
http://www.sys-con.com/java/readerschoice2003/index.cfm
The ColdFusion Developer's Journal is also hold it's Readers' Choice Awards, for which several Macromedia products have been nominated. Have a look and cast your vote here:
http://www.sys-con.com/coldfusion/readerschoice2003/index.cfm
Finally, Web Services Journal and XML Journal are jointly holding their Readers' Choice Awards. Both Macromedia ColdFusion MX and JRun 4 have been nominated in the "Best App Server for Web Services" category. And ColdFusion MX has also been nominated as the "Most Innovative Application of XML". Make your opinions known here:
http://www.sys-con.com/webservices/readerschoice2003/index.cfm
And, of course, check out the "ColdFusion & Java" story by Ben Forta while you are there.
Posted by cantrell at 11:01 AM. Link | References
April 1, 2003
Remember that JSP eq Java
I was talking to someone last week who needed to use some Java in his ColdFusion application, but couldn't because of limitations with his hosting provider's configuration which prevented him from making changes to the ColdFusion server's classpath. I actually don't know how much freedom developers who use shared hosting environments have when it comes to integrating Java and ColdFusion (perhaps some people can comment here), however it occurred to me that one possible work-around is to embed all your Java in JSPs (assuming the hosting provider is using ColdFusion Enterprise). JSPs get compiled into Java classes, so as long as you are doing something relatively simple, there is really no reason why you can't simply include your Java between scriptlet tags. Scriptlet tags look like this:
<%
// java code here
%>
You can declare members (methods and variables) using declaration tags, like this:
<%!
String foo = "bar";
private String getFoo()
{
return foo;
}
%>
Use an expression tag to access members:
<%= getFoo() %>
For an explanation of all JSP tags, see:
http://java.sun.com/products/jsp/syntax/1.2/syntaxref12.html
Again, you're not going to write an entire application like this (eventually, you are going to need access to the classpath), but in a pinch, you might find this technique useful.
Posted by cantrell at 10:50 AM. Link | Comments (1) | References
March 25, 2003
Getting JRun and CFMX to Work With Java 1.4.1 on OS X
Thanks to Woojin Choi for posting information on getting JRun to work with Java 1.4.1 on OS X. I have made a couple of adjustment to what Woojin posted to match what I found to be effective:
First, back up the jvm.cfg file found here (you will need to use 'sudo' to make these changes):
/System/Library/Frameworks/JavaVM.framework/Versions/1.4.1/Home/lib/jvm.cfg
Edit jvm.cfg. Change this...
-client KNOWN -jvm ALIASED_TO -client -hotspot ALIASED_TO -client -server KNOWN -classic WARN
... to this ...
-client -jvm -hotspot -server -classic
Edit {jrun_installation_dir}/bin/jvm.config, and change this...
java.home=/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Home
... to this ...
#java.home=/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Home java.home=/System/Library/Frameworks/JavaVM.framework/Versions/1.4.1/Home
Give it a try and see what happens!
Posted by cantrell at 2:44 AM. Link | References
March 24, 2003
Making Your ColdFusion Applications More Platform Independent (Part II)
Last Friday, I made a post about writing platform-independent ColdFusion code, and specifically how important it is to be consistent with case when you are naming and referencing files since Unix file systems are case sensitive. The other practice I often see people do which keeps code from being platform independent is hardcoding file separators. The Windows file separator is a "\" (backslash character), however the file separator on Unix file systems is a "/" (forward slash character). The Macintosh file separator is a ":" (colon character), however the OS X file system will let you get away with a Unix-like "/" file separator. If your application needs to construct file paths, and you want your code to be truly platform independent, you will need to take these differences into account.
There are two good ways to make your file separators dynamic. The first is to define the system's file separator in the Application.cfm file or other file where you keep configuration parameters. For instance, if you add this to your Application.cfm file...
<cfset request.FILE_SEPARATOR = "/" />
... rather than hardcoding slashes throughout your code, you can then simply refer to the request.FILE_SEPARATOR variable.
You can make your life even easier by letting ColdFusion (or, more precisely, Java) figure out what the system's default file separator is for you with the following function:
function getFileSeparator()
{
var fileObj = "";
if (isDefined("application._fileSeparator"))
{
return application._fileSeparator;
}
else
{
fileObj = createObject("java", "java.io.File");
application._fileSeparator = fileObj.separator;
return getFileSeparator();
}
}
This function actually caches the file separator for you the first time you call it so that you are not instantiating a new java.io.File object each time you call it, however if you prefer to have your calling code do the caching, naturally you can re-factor the function appropriately. The point is that by not hardcoding your file separators, your code is much more platform independent, and much easier to port from one OS to another.
Posted by cantrell at 2:21 PM. Link | References
February 28, 2003
Couple of Useful Custom Tags
It was pointed out the other day on a list that cfinclude doesn't let you include JSP pages and that there is no cfforward tag to forward a request on to another resource (CFM, JSP, servlet, etc.). BlueDragon apparently does have this functionality. Well, now ColdFusion does, too, with the extremely simple tags below. And ColdFusion also has getPageContext(), as well.
<!---
The includeanything tag will include any type of page, not just a
CFM template.
@attribute page (required) Relative path to the template you want
to include.
--->
<cfif thisTag.executionMode is "start">
<cfparam name="attributes.page" />
<cfscript>
getPageContext().include(attributes.page);
</cfscript>
</cfif>
<!---
The forward tag will perform a server-side redirect.
@attribute page (required) Relative path to the template you want
to forward to.
--->
<cfif thisTag.executionMode is "start">
<cfparam name="attributes.page" />
<cfscript>
getPageContext().forward(attributes.page);
</cfscript>
</cfif>
Posted by cantrell at 11:57 AM. Link | Comments (2) | References
Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy (updated 07-14-2009).