Curtis Schlak

Subscribe to Curtis Schlak: eMailAlertsEmail Alerts
Get Curtis Schlak: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: ColdFusion on Ulitzer, Java EE Journal

CFDJ: Article

Stimulants and Science Fiction

Stimulants and Science Fiction

I'm writing my Congressional representative. I'm going to ask him if he can introduce a bill on the floor to declare May 29 as "Curtis Is Really Happy Day."

One of his assistants will ask about my motivations, of course. I'll just forward the e-mail I received the morning of May 29, 2002, announcing the commercial release of ColdFusion MX. My representative's assistant will peg me as some weirdo and forward my contact information to the FBI where they can just add it to the fat file sitting on AD Skinner's desk. It's worth it, though.

If you don't already know, CFMX is built on Java 2, Enterprise Edition (J2EE) technology. This means that the voodoo that the ColdFusion Application Server used to perform on ColdFusion templates during the compilation process is no longer practiced; ColdFusion now compiles ColdFusion templates to Java bytecode that can be run with CFMX or Macromedia ColdFusion MX for IBM WebSphere.

In the middle of my celebration of this amazing development, I realized that the entire subject matter for this article had changed. I had to change the way I approached the topic and the examples in it. It would be pretty silly to read an article about Java and XML when that functionality is built into CFMX.

I don't expect that everyone reading this has gone out and purchased CFMX. I still develop in ColdFusion 4.0 for a client of mine who refuses to invest in upgrading. They also run MS WinNT 4.0 on a DEC Alpha machine with MS SQL Server 7.0, so I don't see their purchase of CFMX occurring anytime soon. Even the deep-pocket clients I develop for don't have plans for purchasing a CFMX upgrade until Q4.

With these factors in mind, it only seems reasonable to develop the same miniapplication for both the ColdFusion 5.0 and ColdFusion MX architectures, highlighting the power of CFMX along the way. If you don't have CFMX and would like to complete the parallel development, you can download the CFMX trial version from the Macromedia site.

The Quandary
ColdFusion is great at retrieving data and formatting it for display; however, until CFMX it has only been a scripting language. Version 5 introduced user-defined functions that altered the top-to-bottom processing of ColdFusion templates. CFMX introduces ColdFusion Components, which seems like a tag-based way of creating classes, a quantum leap for the language.

Now that developers can create CFCs, the question is, Why write external Java classes to supplement the functionality of ColdFusion when ColdFusion MX has so many features? The answer is quite simple, really. Java has a rich set of classes and interfaces that can make a developer's work easier. During the course of this article, we'll leverage a small portion of this library to analyze a set of simple data with some complex relationships. We'll implement it as a ColdFusion extension (CFX), as an object instantiated through the use of <CFOBJECT>, and as a servlet integrated into the CFMX architecture.

The Product
This article will analyze a two-player, online version of Go. For those of you who play Go, you know how intense and complex the game is. If you're unfamiliar with the game, there are only nine rules:

  1. The board starts out empty.
  2. A move consists of playing a piece on an empty intersection.
  3. A piece or a solidly connected group of pieces is captured when completely surrounded by the opponent's pieces.
  4. Captured pieces are removed from the board.
  5. The previous board position may not be recreated.
  6. A player may not place a stone such that it would cause the immediate capture of that stone or the group to which it belongs.
  7. A player may pass on any turn.
  8. The game ends when both players pass in sequence.
  9. The player that captures the largest portion of the board wins.
Without using objects, a programmer most probably will resort to recursion to analyze the pieces on the board. This type of programming can be expensive in terms of resources and time. Creating the appropriate objects to represent the game board and groups of pieces can allow for easy analysis of the board.

This architecture will implement the analysis portion of those rules using Java classes to analyze each move's validity and update the structure that represents the board. We'll use ColdFusion to create the HTML to present the information and to retrieve it from WDDX packets saved to the server.

The serialized game data structures will be stored in two standard XML templates: games.wddx and template.wddx. The WDDX schema was chosen because it's the only XML schema that ColdFusion 5 supports natively. CFMX, built on Java technology that has had XML parsing support for a long time, can use XML packets with any schema, including WDDX. Hence, for interoperability between the two server versions, WDDX is our choice.

Stored in games.wddx is an array of structures serialized as a WDDX packet. The structure holds the create date of the game, the name of the game, and the file in which the individual game information has been serialized. Those individual game files are stored in the data directory. The choice to use WDDX in this instance is merely to circumnavigate the need for a database.

Stored in template.wddx is the initial structure of a game, where both players have captured none of their respective opponent's pieces and the Go board is empty. To allow for a clearer analysis of the data in this example code, the board is stored as a query serialized into a WDDX packet with 19 columns and 19 rows. There are more economical ways to store the data. This is not production-quality data storage, but example-quality data storage.

The Code
The ColdFusion code remains the same through all the different implementations with the exception of the template that calls the validation algorithms. Memory variables, such as SERVER-, APPLICATION-, and SESSION-scoped variables, aren't present in this application; however, it's important to point out that ColdFusion MX allows the use of J2EE session identifiers in addition to the CFID and CFTOKEN values to which we've all become accustomed. If the "Use J2EE sessions" option is turned on in the CFMX Administrator, then servlets and JavaServer Pages can share information that's stored in the APPLICATION and SESSION scopes. While we won't see this in the code, I'll point out possible uses at the appropriate times.

The code must check the version of the ColdFusion server that's running this game because it's supported only by ColdFusion 5.0 and higher. The CFX implementation would probably run on ColdFusion 4.5, but it hasn't been tested. This version test is performed as the first step in the Application.cfm. If a nonvalid version of ColdFusion is found to be running, the user is relocated to error.htm, a simple page that informs users to upgrade their version of ColdFusion. The Application.cfm also sets up the variables that contain the path to the file that contains a WDDX packet listing the current games, a variable that points to the current-move validation template, and a portion of code that intercepts the request to create a new game. That interception appends the new game to the game details structure and reserializes it for storage. There are also instructions for configuring each of the validation templates and their resources.

The default template, index.cfm, reads the data from games.wddx and displays it, as well as presents a text field to the player to create a new game. Both the form and the links surrounding the game titles point to board.cfm.

The actual game is played from board.cfm, where a graphical representation of the board is drawn. Each image of the playing field contains an intersection; if the intersection is empty (there's no piece on it), then it's a hyperlink to a validation page, where the interesting portion of the code exists.

OnRequestEnd.cfm uses a CFDUMP on the REQUEST scope if the parameter request.debug.show-Structures is present and evaluates to a value that's considered TRUE by ColdFusion. That dump of the contents of the REQUEST scope shows all the pertinent information gathered by the data retrieval processes.

There are four validation templates: validateMoveCFX.cfm, validateMoveCFOBJECT5.cfm, validateMoveCFOBJECTMX.cfm, and validateMoveServlet.cfm. The servlet will be used to highlight one of the new features of CFMX, using servlets by including them directly into ColdFusion. Each of the templates is named with its respective mode of move validation.

Two basic Java classes are used to model the Go board: Board and Group, which are stored in the subdirectory com/grayiris/go and belong to that package. The Group object holds information about how many pieces are in the group and how many empty spaces there are around the group. If the number of those empty spaces reaches zero, then that group is captured and will be removed from the board. The number of pieces in that group will be added to the current player's prisoner total.

Board models all the states that the board has gone through in the course of a game and which empty spaces on the board are adjacent to which Group object. It also contains Group objects that represent the groups of pieces on the Go board for the current state of the board. BoardFactory contains a static method createBoard() that will initialize a board object from a complex structure passed to it. All that's left is to integrate these into the ColdFusion application.

CFX Implementation (CF5 & CFMX)
If you've never used a CFX tag, it's like using a custom tag written in ColdFusion Markup Language except that the syntax is slightly different. When invoking a custom tag written in CFML, you type <cf_filename> and ColdFusion looks around for the file and runs it in its own process. CFXs are similar, but are written in Java or C++. You must register the CFX in the ColdFusion Administrator on the "CFX Tags" page. One of the major advantages of writing CFXs in Java is thread safety; since each Java CFX class has its own associated Class-Loader that loads it and any dependent classes, per-request information is safe to store in the CFX.

The C++ version isn't done this way, and the developer must make the code thread-safe, adding another level of tedium. But if you have a performance-sensitive application and need the fastest code possible, the C++ extension is really the way to go. For this article, however, all information in this section is applicable only to CFXs written in Java.

CFXs have a query attribute through which a reference to a ColdFusion query object is passed. That query and its associated metainformation, such as row count and column names, can be retrieved through the getQuery() method of the Query Interface of the ColdFusion extension API. The query passed into CFX_ValidateGoMove is the query that's retrieved from the WDDX packet stored in the game file. It contains the history of the board from the first to the current move. The CFX instantiates a Board object and populates it with the information from the query. How the CFX is used is shown in Listing 1.

If the move succeeds, a variable with a name equal to the string passed into the CFX in the invalidMoveBoolName attribute will contain a 1. A WDDX packet will be created in the variable with the name that you passed into the newBoardWDDX-Name, which can be saved directly to the game file. If the move failed, then a variable with a name equal to the string passed into the CFX in the invalidMoveBoolName attribute will contain a 0 and a variable will be created with the name passed in through the reportStringName attribute. We pass that back as the error message.

CFOBJECT Implementation
(CF5 & CFMX)

The difference in implementing the Board object with CFOBJECT in ColdFusion 5 and CFMX is the method of delivery of the information to the object created by CFOBJECT. CF 5 doesn't support automatic conversion of Date/Time objects and structures to Java objects. CFMX, now built in Java, has a greater capacity for sending and receiving information from ColdFusion with automatic conversion of structures, arrays of different element types, and queries. (The CFMX documentation states that a ColdFusion Query object can be cast as a Java object implementing the Map interface. However, with the version I'm running [6,0,0,46617] I can't get this functionality to work.) This will allow us to pass the information to our object more easily in CFMX than in CF5. The latter implementation is the file validateMoveCFOBJECT5.cfm; the CFMX implementation is the file validateMoveCFOBJECTMX.cfm.

In CF5 the Board object is created and then populated with the information from our query by repeating a call to the setBoardState() function. In CFMX we can send the entire structure built from the game file to the BoardFactory and it will return a Board object. After these objects have been created and their information loaded, we call the makeMove() method, which returns a Boolean value, true if the move succeeded and false if it failed. From that information we fork the code, sending the reason for failure back to the browser, or retrieving the WDDX packet for the new game state with the getWDDXBoard() method, and save that string to a file.

Servlet Implementation (CFMX Only)
I won't lie to you: this implementation is the most exciting for me. It allows the seamless integration of JSPs and Java servlets with ColdFusion templates.

The ColdFusion template validateMoveServlet.cfm reads the information from the game file, just like the rest. It then includes the servlet, which can access that structure through the request scope with the getParameter() method found in the request interface. The structure is then cast as a Map and everything works as before. A BoardFactory returns the appropriate Board object from the query stored in the structure. The same processing is completed and the servlet then sets variables in the request scope that ColdFusion can then access. Voilà!

A Marriage Made in Heaven
Java is an appropriate solution in many situations. ColdFusion has allowed us to harness that power for a few years. However, with the release of ColdFusion MX, the power of Java now propels ColdFusion. We can integrate servlets and JSPs directly into our applications without the overhead of creating HTTP requests and waiting for answers. We can now share APPLICATION- and SESSION-scoped variables with these previously untouchable objects. CFMX allows for tighter integration of data through automatic conversion of native ColdFusion data types to native Java types.

Resources

  • Java 2 Platform, Enterprise Edition: http://java.sun.com/j2ee/
  • Macromedia ColdFusion MX for IBM WebSphere: www.ibm.com/software/webservers/coldfusionmx/
  • Macromedia MX - Free Product Evaluations: www.macromedia.com/software/trial_download/
  • Go Rules: www.usgo.org/
  • More Stories By Curtis Schlak

    Curtis received a BS in mathematics with a minor in English. His first self-published textbook, The Sad Book of Calculus: A Textbook Supplement, sold out. During a spell in the Army, he integrated Microsoft products with legacy dBase logistics software and wrote his first Web application. He was a senior director of development (ColdFusion) at KickFire, Inc., in Saratoga, Calif.He has now started a new company, Striatum Solutions, in Houston.

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.