YOUR FEEDBACK
Ben Forta's ColdFusion Blog: SQL Injection Attacks, Easy To Prevent, But Apparently Still Ignored
Luis Melo wrote: Our system was not SQL Injection proof and we recently su...
AJAXWorld RIA Conference
$300 Savings Expire July 25
Register Today and SAVE!


2007 West
GOLD SPONSORS:
Active Endpoints
Your SOA Needs BPEL for Orchestration
BEA
Virtualized SOA: Adaptive Infrastructure for Demanding Applications
Nexaweb
Overcoming Bandwidth Challenges with Nexaweb
TIBCO
What is Service Virtualization?
SILVER SPONSORS:
WSO2
Using Web Services Technologies and FOSS Solutions
Click For 2007 East
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
TOP COLDFUSION LINKS


Reading File as from Java
Sometimes using cffile isn't enough - here's how Java can help

Digg This!

I open my e-mail this morning to find that one of my clients had sent me a file for import to their database. The file is comma delimited. Importing it into SQL Server is fairly simple with Data Transformation Services (DTS), however there's a catch.

The file contains a list of employees and EmployeeIDs. The EmployeeIDs are considered super sensitive, and must be encrypted. DTS can't be used to encrypt data before storing it in the database, so I'll need to do something else. The client didn't send me encrypted data, so what do I do?

Dissecting the Problem
In the past we've used a custom tag to encrypt the data with a BlowFish encryption scheme. (Note: This encryption is built into CFMX7, but the client hasn't upgraded yet). I can perform the encryption in ColdFusion. Maybe I can use cffile to read in the information? Let's see, the file has 60,000 records. The thought of loading so much data into memory and then having to parse it via CF does not sound like a fun project. Is there another way? Well, yes there is.

For 99.9% of the tasks that you perform daily, you'll never need to look beyond the functionality that ColdFusion provides to you, right out of the box. However, once in a while you come across something that you just can't do easily (or at all) from within ColdFusion. Thankfully, ColdFusion is now built on top of Java and you have access to the full array of Java-based objects. Random file access can be done in Java, but not from within CF. Random file is just a fancy way to say that you can access any point in the file, usually by providing the character number of the file. Using some specialized methods, we can also read a file line by line, which is the example we'll explore more in this article.

Here is a simplified version of our client file:
Last Name, First Name, EmployeeID
Arehart, Charlie, 78934
Helms, Hal, 78903
Horwith, Simon, 54321
Houser, Jeff, 12345

The first record in the file is a header record, naming the columns and the order they appear. Following the header row we have lots of data. For simplicity, I've cut out a lot of the information you would probably receive from the client, such as contact information and company position. The goal is to read in one line from the file, process the record, and then repeat until there are no more entries in the file.

There are two Java classes that we need to make use of to be able to read in the file. The first is BufferedReader class, or java.io.BufferedReader. This class is used to read text from any character input stream. Various items can be used as input streams, but in our case we want to use a text file. Full documentation for the BufferedReader class is located here: http://java.sun.com/j2se/1.4.2/docs/api/java/io/BufferedReader.html.

A constructor, or init method, is a way to initialize a Java object, and many Java objects have one or more constructors. There are two constructors of the BufferedReader class. Both accept a Reader object. One also accepts the size of the input buffer stream. For our purposes we can use the default input buffer stream. But, what is a reader object, and where do we get it?

A reader object is an object created from the reader class. Due to the nature of Java, any subclasses of the reader class can also be accepted as constructor argument. Documentation on the reader class is located here http://java.sun.com/j2se/1.4.2/docs/api/java/io/Reader.html, but the subclass of reader that we are really interested in is the FileReader class, located here: http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileReader.html. The FileReader class is designed for reading in information from a file. It has three different constructors, but the one we are going to use accepts a string that is the location of the file.

The process to follow is to create and init the FileReader class. Then create and init the BufferedReader class using the FileReader class. After that, you can call various methods on the BufferedReader class, such as read to get a specified number of characters or readLine to read a full line of text. All this is interesting, but how do we access the Java Classes from within ColdFusion?

Creating the Java Objects with cfobject and CreatObject
There are two ways you can create Java objects with ColdFusion. One method uses a tag, and the other users a function. They are both similar, so I'll teach you both of them. From within CFML, you can use the cfobject tag; In CFScript the CreateObject tag is your tool for object creation. The attributes for the tag are very similar to the function's parameters. This is the list of parameters:

  • Type: cfobject can be used to create many types of different objects, such as Web services, CFCs, and Java objects. The type attribute is used to specify what kind of object you are creating. Since we are creating a Java object, we'll give it the value of "Java". This is also the first parameter passed into the CreateObject function. It is required in both methods.
  • Class: The class attribute is used to define the name of the Java class that you want to create. There are many Java objects for various different purposes. You can find the complete list here http://java.sun.com/j2se/1.4.2/docs/api/allclasses-noframe.html. The class is the second and final parameter of the CreateObject function. It is required.
  • Action: The action attribute is used to tell the tag to create the object. Its only valid value is "create". It is required for the cfobject tag, but has no parallel in the CreateObject function.
  • Name: The name attribute specifies the name of the variable that will contain the reference to the newly created object. It is required for the cfobject tag. When using the CreateObject function, this value is the one on the left side of the equal sign, similar to a cfset.
To use cfobject create an object of the FileReader class you would use code like this:

<cfobject type="Java" class=" java.io.FileReader" Action="Create" name="fileReader">

To implement the same command using the CreateObject Function, you might use code like this:


<cfset FileReader = CreateObject("Java"," java.io.FileReader")>

Or you could execute the function inside of a CFScript block, like this:


<cfscript>
 FileReader = CreateObject("Java"," java.io.FileReader");
</cfscript>

All Java objects have a collection of methods associated with them. The names and functionalities of these methods depend upon which object you are creating an instance of. To call a method against an object you must use something called Object Property notation. You are probably already familiar with Object Property notation, because you can use it to reference columns against a query variable, or keys in a structure, or methods in a CFC.

Object Property notation consists of the variable name of the object, followed by a dot, then the property or method you want to access. If calling a method, enclose the argument list in parenthesis. Most Java objects have one or more init methods. One of the init methods on our FileReader object accepts the disk location of the file. You'll probably call it like this:


<cfset Result = fileReader.init("C:\test.txt");

Since Java does not have named arguments, you cannot use cfinvoke to call methods against a Java object. Many developers prefer to use CFScript when invoking and using objects because the Object Property notation lends itself better to CFScript than to CFML.

Reading the File
Let's take a look at the code:


<cfscript>
 fileReader = CreateObject("java", "java.io.FileReader");
 fileReader.init("C:\\test.txt");
 br = CreateObject("java", "java.io.BufferedReader");
 br.init(fileReader);
 
 // Counters for the loop
 TotalNumRecords = 0;
</cfscript>

<cftry>
 <cfloop condition="true">
 <cfscript>
  line = br.readLine();
 </cfscript>
 <Cfset TotalNumRecords = TotalNumRecords + 1>
 <cfoutput>
  Line #TotalNumRecords#: #Line#<br>
  <!---- other processing ---->
 </cfoutput>
 </cfloop>
 <cfcatch type="coldfusion.runtime.
	UndefinedVariableException">
 <!--- this indicates end of file, ok to ignore error --->
 </cfcatch>

</cftry>

As discussed earlier, the code starts out by creating a FileReader object. The full path name for the FileReader is java.io.FileReader. Then it initializes that object, giving it the location of a file. The next line creates the BufferedReader object. The full path name for the Buffered-Reader object is java.io.BufferedReader. The init method on BufferedReader object uses the fileReader object as input.

The code does not assign the results of the init operation to any variable, although you could if you wanted. ColdFusion returns the name of the Java object and its location in memory. There isn't much you can do with the information in the context of ColdFusion.

Normally, in Java or other programming languages, you would loop over the input stream until you received an end of file character. Within each loop you would read the next line. CF doesn't have the concept of an end of file character, but we can work around this using the cftry and cfcatch error tags. The code uses a condition loop, with the condition being true. That means the loop will never end. However, the loop is inside a cftry block and the cfcatch is outside of the loop. The catch block will catch an undefined variable exception. When the code in the loop reads the next line and it's not there, this exception will catch when it tries to read the variable.

The code inside the loop is the simple part. It uses the readLine method on the BufferedReader variable to get the next line. It increments counter variable TotalNumRecords and displays the line to the screen. Any additional processing, such as encrypting the data and storing it in the database, is left out of this example, because you know how to do all that.

If not, read up on encryption here http://livedocs.macromedia.com/coldfusion/ 6.1/htmldocs/functi75.htm#wp1104201 and using the cfquery tag http://livedocs.macromedia.com/coldfusion/ 6.1/htmldocs/tags-b19.htm#wp1102316.

A Final Thought about CF, Macromedia, and Adobe
I am writing this article fewer than 24 hours after Adobe and Macromedia announced that they would be merging into a single company yet. The mailing lists and blogs are awash with a mix of despair and excitement, or sometimes both. When I write articles like this, I can't help but think about the power that lies in our hands with the ability to write ColdFusion code. No matter what the future plans are, I can't help but look forward with optimism. Rest assured I hope that this event will officially end the "Microsoft wants to buy Macromedia" doomsday threads.

About Jeffry Houser
Jeffry Houser has been working with computers for over 20 years and in Web development for over 8 years. He owns a consulting company and has authored three separate books on ColdFusion, most recently ColdFusion MX: The Complete Reference (McGraw-Hill Osborne Media).

CFDJ LATEST STORIES . . .
Adobe's Kevin Lynch and Microsoft's Scott Guthrie to Keynote AJAX World RIA Conference & Expo
Two of the biggest launches in Rich Internet Application history took place in 2007/2008 when Adobe launched AIR 1.0 in February '08 and Microsoft launched Silverlight (September '07). At the 6th International AJAXWorld RIA Conference & Expo in October SYS-CON Events is delighted to be
Voyager Offers Android, .NET CF, Java Runtime Support
Recursion Software released a private beta version of their Voyager mobile platform, with powerful interoperability for Android, Microsoft .NET and Compact Framework (CF), all Java editions (JME CDC, JSE and JEE), and more than 15 embedded operating systems. The Voyager platform is a p
AJAX and Enterprise RIA Tools - JSF, Flex, and JavaFX
2008 is going to be an important year for Rich Internet Applications. Most organizations are delivering or planning to deliver Rich Internet Applications; however, at the same time, most IT managers are facing a dilemma: which Rich Internet Application technology and platform to use? T
CFDynamics Announces Renewed Agreement with SmarterTools
CFDynamics, a ColdFusion web host, has renewed an agreement with SmarterTools that will allow them to pass on immediate value to their customers. When a customers signs up for a dedicated hosting account they will now receive $750 worth of features including SmarterMail, SmarterStats a
Microsoft's Virtualization Chief Mike Neil To Keynote SYS-CON's Virtualization Conference & Expo
Mike Neil is general manager for virtualization strategy in the Windows Server Division at Microsoft. Mike is focused on the delivery of the Windows virtualization technology, including Windows Server 2008 Hyper-V, Microsoft Hyper-V Server and Virtual PC 2007. Mike also directs the tec
SYS-CON's Virtualization Conference & Expo: Themes & Topics
From Application Virtualization to Xen, a round-up of the virtualization themes & topics being discussed in NYC June 23-24, 2008 by the world-class speaker faculty at the 3rd International Virtualization Conference & Expo being held by SYS-CON Events in The Roosevelt Hotel, in midtown
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE